Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@dyc3
Copy link
Contributor

@dyc3 dyc3 commented Nov 3, 2025

Summary

Adds benchmarks for both the useSortedClasses parser and biome_tailwind_parser.

This was mostly generated with AI. The useSortedClasses benches are a little verbose I'll probably trim it down a bit.

Test Plan

cargo bench --bench use_sorted_classes_parser
cargo bench --bench tailwind_parser

Docs

@changeset-bot
Copy link

changeset-bot bot commented Nov 3, 2025

⚠️ No Changeset found

Latest commit: e37d41b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor Author

dyc3 commented Nov 3, 2025

@github-actions github-actions bot added A-Linter Area: linter A-Parser Area: parser L-JavaScript Language: JavaScript and super languages L-Tailwind Language: Tailwind CSS labels Nov 3, 2025
@dyc3 dyc3 marked this pull request as ready for review November 3, 2025 21:53
Copy link
Member

@ematipico ematipico left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the first time I've seen that profiler. How does it work? Why do we need it? Also, any reason why we use criterion instead of divan? (It's the recommended choice now)

@dyc3
Copy link
Contributor Author

dyc3 commented Nov 3, 2025

TBH I'd forgotten we switched to divan. Criterion is just my go-to.

The profiler was the one recommended by criterion in their docs, and it was the easiest way to get profiling info from the benchmark (that I'm aware of).

@dyc3
Copy link
Contributor Author

dyc3 commented Nov 3, 2025

It also looks like I need to change our CI triggers so that stacked PRs can trigger the CI

@ematipico
Copy link
Member

Thank you! I just wanted to know :) there are things that can't be done with divan yet, so that's why we still use both. What's the profiler for? I'm curious because I don't recall using it in the other benchmarks

@dyc3 dyc3 force-pushed the dyc3/add-tw-bench branch from 9be1519 to 41bf9cb Compare November 4, 2025 11:21
@dyc3 dyc3 force-pushed the dyc3/fix-inset-parsing branch from 564d878 to 13dd0b9 Compare November 4, 2025 11:21
@dyc3
Copy link
Contributor Author

dyc3 commented Nov 4, 2025

The profiler produces a file that you can load up in pprof, which has flame graphs and a directed graph that shows what is calling what, and how much total time it takes. It's more popular in the golang world.

It's how I figured out we were double lexing base names (once when parsing VariantList and once for the actual base name)

I've removed it for now because I don't need it anymore, and we can always add it back in later.

@dyc3 dyc3 changed the base branch from dyc3/fix-inset-parsing to graphite-base/7976 November 8, 2025 19:23
@ematipico
Copy link
Member

Anyway, it's possible you missed my comment because it's in the other PR.

This benchmark, to take effect, should be merged in next or main

@dyc3
Copy link
Contributor Author

dyc3 commented Nov 9, 2025

They must have changed the behavior of graphite. I was expecting this to get pointed to main after merging the previous one.

@dyc3
Copy link
Contributor Author

dyc3 commented Nov 9, 2025

I think it didn't do it automatically because there's a merge conflict

@dyc3 dyc3 force-pushed the graphite-base/7976 branch from 13dd0b9 to 846feee Compare November 9, 2025 09:52
@dyc3 dyc3 force-pushed the dyc3/add-tw-bench branch from 41bf9cb to 1d6d214 Compare November 9, 2025 09:52
@dyc3 dyc3 changed the base branch from graphite-base/7976 to main November 9, 2025 09:52
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 9, 2025

Walkthrough

Adds a GitHub Actions workflow "Benchmarks Tailwind" that runs cargo-codspeed/CodSpeed benchmarks. Introduces Criterion-based bench targets and new benchmarking modules in crates/biome_tailwind_parser and crates/biome_js_analyze, plus multiple large fixture files under their benches/fixtures directories. Updates Cargo.toml entries (dev-dependencies, bench declarations) for those crates and makes class_lexer public to permit bench access. Also tweaks three parser assertion messages to include the current token range.

Possibly related PRs

  • ci: breakdown benchmarks #7641: Adds/updates CodSpeed benchmark GitHub Actions workflows and related benchmark artifacts with similar crate-scoped CI changes.

Suggested labels

A-Tooling

Suggested reviewers

  • ematipico
  • siketyan

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: adding benchmarking infrastructure for the Tailwind parser and related components.
Description check ✅ Passed The description accurately explains the changeset, disclosing AI assistance and providing clear testing instructions for the added benchmarks.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dyc3/add-tw-bench

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
crates/biome_tailwind_parser/benches/tailwind_parser.rs (1)

1-76: CI integration still pending.

As noted in previous review, these benchmarks won't execute until integrated into the CI workflow.

🧹 Nitpick comments (5)
.github/workflows/benchmark_tailwind.yml (2)

10-25: Consider narrowing the path filter.

The pattern crates/biome_tailwind_*/**/*.rs is quite broad and may trigger benchmarks unnecessarily for unrelated Tailwind crates. If possible, tighten this to match only the specific crates you intend to benchmark (e.g., crates/biome_tailwind_parser/**/*.rs), or keep it intentionally broad if you expect multiple tailwind packages to evolve together.


37-40: Matrix strategy has a single package.

The matrix presently contains only biome_tailwind_parser. If you intend to add more benchmark targets later, this is a good foundation; otherwise, you could flatten the config. Keep as-is if extensibility is planned.

crates/biome_tailwind_parser/benches/tailwind_parser.rs (1)

26-42: Consider sorting fixture names for deterministic ordering.

The fixture names are read from the filesystem without sorting, which may lead to non-deterministic benchmark ordering across different platforms or filesystems.

Apply this diff:

 fn fixture_names() -> impl Iterator<Item = String> {
     let fixtures_dir = Path::new("benches/fixtures");
     let mut names = Vec::new();
 
     if let Ok(entries) = std::fs::read_dir(fixtures_dir) {
         for entry in entries.flatten() {
             let path = entry.path();
             if path.is_file() {
                 if let Some(file_name) = path.file_name().and_then(|n| n.to_str()) {
                     names.push(file_name.to_string());
                 }
             }
         }
     }
 
+    names.sort();
     names.into_iter()
 }
crates/biome_js_analyze/src/lint/nursery/use_sorted_classes.rs (1)

3-3: Public exposure of class_lexer for benchmarking.

Whilst this enables the benchmark to access tokenize_class, it does expand the crate's public API surface. Confirm this is acceptable, or consider whether the lexer should be exposed conditionally (e.g., via a feature flag) if it's not intended for external consumption beyond benchmarking.

crates/biome_js_analyze/benches/use_sorted_classes_parser.rs (1)

53-68: Verify sample size and byte counter semantics.

Two items to confirm:

  1. sample_size=10 is quite low. Is this intentional due to the fixtures being large and the benchmark taking significant time? If not, consider increasing for more reliable statistics.

  2. Byte counter mismatch: Line 62 counts the entire input string's bytes, but the benchmark (lines 64-66) tokenises individual classes after splitting. The counter doesn't reflect the actual work granularity—it over-reports if you're measuring per-class throughput. Consider whether the counter should sum the lengths of individual classes or remain as-is if you're measuring whole-string processing.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0612a5 and 1d6d214.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock and included by **
📒 Files selected for processing (17)
  • .github/workflows/benchmark_tailwind.yml (1 hunks)
  • crates/biome_js_analyze/Cargo.toml (2 hunks)
  • crates/biome_js_analyze/benches/fixtures/arbitrary_classes.txt (1 hunks)
  • crates/biome_js_analyze/benches/fixtures/extreme_stress.txt (1 hunks)
  • crates/biome_js_analyze/benches/fixtures/simple_classes.txt (1 hunks)
  • crates/biome_js_analyze/benches/fixtures/stress.txt (1 hunks)
  • crates/biome_js_analyze/benches/fixtures/variant_classes.txt (1 hunks)
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs (1 hunks)
  • crates/biome_js_analyze/src/lint/nursery/use_sorted_classes.rs (1 hunks)
  • crates/biome_parser/src/lib.rs (3 hunks)
  • crates/biome_tailwind_parser/Cargo.toml (2 hunks)
  • crates/biome_tailwind_parser/benches/fixtures/arbitrary_classes.txt (1 hunks)
  • crates/biome_tailwind_parser/benches/fixtures/extreme_stress.txt (1 hunks)
  • crates/biome_tailwind_parser/benches/fixtures/simple_classes.txt (1 hunks)
  • crates/biome_tailwind_parser/benches/fixtures/stress.txt (1 hunks)
  • crates/biome_tailwind_parser/benches/fixtures/variant_classes.txt (1 hunks)
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs (1 hunks)
🧰 Additional context used
🧠 Learnings (20)
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/crates/**/src/lexer/mod.rs : Create a lexer module at crates/<parser_crate>/src/lexer/mod.rs

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/use_sorted_classes.rs
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Lexer must implement the biome_parser::Lexer trait

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/use_sorted_classes.rs
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : For non-mandatory tokens, use the provided helper constructors (e.g., `token`, `space_token`, `dynamic_token`)

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/crates/biome_*_{syntax,factory}/** : Create per-language crates biome_<lang>_syntax and biome_<lang>_factory under crates/

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
  • crates/biome_parser/src/lib.rs
  • crates/biome_tailwind_parser/Cargo.toml
  • crates/biome_js_analyze/Cargo.toml
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/xtask/codegen/src/*_kinds_src.rs : Add src/<lang>_kinds_src.rs under xtask/codegen that returns a static KindSrc

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/language.rs : Create tests/language.rs defining `HtmlTestFormatLanguage` and implement the TestFormatLanguage trait

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/** : Create a tests directory containing a specs subfolder and the files spec_test.rs, spec_tests.rs, and language.rs

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/**/*.rs : After generation, remove usages of `format_verbatim_node` and implement real formatting with biome_formatter utilities

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
  • crates/biome_parser/src/lib.rs
  • crates/biome_tailwind_parser/Cargo.toml
  • crates/biome_js_analyze/Cargo.toml
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/spec_tests.rs : In tests/spec_tests.rs, generate tests with `tests_macros::gen_tests! {"tests/specs/html/**/*.html", crate::spec_test::run, ""}`

Applied to files:

  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
  • crates/biome_tailwind_parser/Cargo.toml
📚 Learning: 2025-10-15T09:25:05.698Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:25:05.698Z
Learning: Applies to crates/biome_service/src/workspace/watcher.tests.rs : Place watcher tests related to workspace methods in src/workspace/watcher.tests.rs

Applied to files:

  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
  • crates/biome_tailwind_parser/Cargo.toml
📚 Learning: 2025-10-15T09:25:05.698Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:25:05.698Z
Learning: Applies to crates/biome_service/../biome_lsp/src/server.tests.rs : Keep end-to-end LSP tests in ../biome_lsp/src/server.tests.rs

Applied to files:

  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
  • crates/biome_tailwind_parser/Cargo.toml
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Do not attempt to fix code; if a mandatory token/node is missing, return `None` instead

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : When a token is mandatory and present in the AST, use the AST-provided token (e.g., `node.l_paren_token().format()`) instead of emitting a static token

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/xtask/codegen/*.ungram : Nodes for enclosing syntax errors must include the Bogus word (e.g., HtmlBogusAttribute)

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Import and use the `FormatNode` trait for AST nodes

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/xtask/codegen/*.ungram : Bogus nodes must be part of a variant/union (e.g., AnyHtmlAttribute includes HtmlBogusAttribute)

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/lib.rs : Add the provided AsFormat, IntoFormat, and iterator plumbing code to lib.rs

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Use `dbg_write!` to debug and inspect the emitted IR during formatting

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/**/Cargo.toml : Add the specified dev-dependencies under [dev-dependencies] for the test infrastructure

Applied to files:

  • crates/biome_tailwind_parser/Cargo.toml
  • crates/biome_js_analyze/Cargo.toml
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/Cargo.toml : Declare the dependency `biome_js_formatter = { version = "0.0.1", path = "../biome_js_formatter" }` for internal installation

Applied to files:

  • crates/biome_tailwind_parser/Cargo.toml
  • crates/biome_js_analyze/Cargo.toml
🧬 Code graph analysis (3)
crates/biome_js_analyze/benches/use_sorted_classes_parser.rs (1)
crates/biome_tailwind_parser/benches/tailwind_parser.rs (1)
  • main (22-24)
crates/biome_tailwind_parser/benches/tailwind_parser.rs (1)
crates/biome_tailwind_parser/src/lib.rs (2)
  • parse_tailwind (28-31)
  • parse_tailwind_with_cache (15-27)
crates/biome_parser/src/lib.rs (5)
crates/biome_js_parser/src/parser.rs (1)
  • source (165-167)
crates/biome_html_parser/src/parser.rs (1)
  • source (90-92)
crates/biome_tailwind_parser/src/parser.rs (1)
  • source (66-68)
crates/biome_html_parser/src/token_source.rs (1)
  • current_range (170-172)
crates/biome_tailwind_parser/src/token_source.rs (1)
  • current_range (115-117)
🪛 actionlint (1.7.8)
.github/workflows/benchmark_tailwind.yml

36-36: label "depot-ubuntu-24.04-arm-16" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2025", "windows-2022", "windows-11-arm", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-26-xlarge", "macos-26", "macos-15-intel", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)

🪛 LanguageTool
crates/biome_js_analyze/benches/fixtures/stress.txt

[uncategorized] ~1-~1: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...t-slate-600 only-of-type:text-slate-500 only-child:text-slate-400 checked:bg-blue-500 chec...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

crates/biome_tailwind_parser/benches/fixtures/stress.txt

[uncategorized] ~1-~1: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...t-slate-600 only-of-type:text-slate-500 only-child:text-slate-400 checked:bg-blue-500 chec...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

🔇 Additional comments (23)
crates/biome_parser/src/lib.rs (3)

250-262: Enhanced assertion diagnostic information.

Adding the token range to the panic message is a useful improvement for debugging parser issues. Clean and consistent with the other updates.


265-276: Consistent diagnostic enhancement across token-set validation.

Good alignment with the bump method update—maintaining consistency across similar assertion patterns.


325-343: Token-range diagnostic applied uniformly across context-aware bumping.

Excellent consistency. All three core assertion methods now include meaningful diagnostic context.

.github/workflows/benchmark_tailwind.yml (2)

36-36: Clarify the runner label.

The actionlint static analysis tool flags "depot-ubuntu-24.04-arm-16" as an unknown label. If this is a custom self-hosted runner label, you may need to configure actionlint. If it's a Depot cloud runner label, verify it's correct for your setup. Either way, the workflow will fail without a valid runner.


42-69: Workflow structure looks solid.

Good use of pinned action versions for reproducibility, sensible permissions, reasonable timeouts, and proper CodSpeed integration. The checkout strategy using github.event.pull_request.head.sha correctly handles both PR and push events.

crates/biome_tailwind_parser/benches/fixtures/extreme_stress.txt (1)

1-1: Fixture looks good for stress testing.

The extensive class string provides excellent coverage for benchmarking parser performance under load.

crates/biome_tailwind_parser/Cargo.toml (1)

28-45: Benchmark dependencies configured correctly.

The use of codspeed-divan-compat aligns with the project's benchmarking strategy, and the allocator configuration follows established patterns.

crates/biome_tailwind_parser/benches/fixtures/arbitrary_classes.txt (1)

1-1: Good coverage of arbitrary values.

This fixture appropriately tests parsing of bracket notation and arbitrary values.

crates/biome_tailwind_parser/benches/fixtures/stress.txt (1)

1-1: Comprehensive stress test fixture.

Excellent variety of Tailwind utilities including responsive variants, state modifiers, and filters.

crates/biome_tailwind_parser/benches/fixtures/simple_classes.txt (1)

1-1: Solid baseline fixture.

Covers common Tailwind utilities well for establishing performance baselines.

crates/biome_tailwind_parser/benches/fixtures/variant_classes.txt (1)

1-1: Targeted variant testing.

This fixture effectively stresses variant and modifier parsing with chained prefixes and pseudo-classes.

crates/biome_tailwind_parser/benches/tailwind_parser.rs (2)

44-57: Cloning overhead may skew uncached benchmark results.

Line 51 clones the entire code string on each iteration. Whilst this ensures a fresh input, the allocation overhead is included in the benchmark timing, which might not reflect pure parsing performance.

Consider whether the allocation overhead is intentional or if you'd prefer to use a reference to avoid this:

bencher
    .counter(BytesCount::of_str(&code))
    .bench_local(|| {
        let result = parse_tailwind(&code);
        divan::black_box(result);
    });

59-76: Cached benchmark setup looks sensible.

The warm-up approach correctly pre-populates the cache before timing begins, providing an accurate measure of cached parsing performance.

crates/biome_js_analyze/benches/fixtures/extreme_stress.txt (1)

1-1: Fixture data looks appropriate for stress testing.

This comprehensive class string effectively exercises the parser with a wide range of Tailwind utilities, variants, and arbitrary values.

crates/biome_js_analyze/benches/fixtures/simple_classes.txt (1)

1-1: Good baseline fixture for simple cases.

This provides a representative sample of common Tailwind utilities without excessive complexity.

crates/biome_js_analyze/benches/fixtures/variant_classes.txt (1)

1-1: Well-targeted fixture for variant parsing.

This effectively tests the parser's handling of complex variant combinations and chaining.

crates/biome_js_analyze/Cargo.toml (2)

58-58: Standard divan setup.

The dev-dependency correctly uses the codspeed-compatible wrapper, consistent with the project's benchmarking infrastructure.


77-79: Benchmark target properly configured.

The harness = false setting is correct for divan, which provides its own benchmark harness.

crates/biome_js_analyze/benches/fixtures/arbitrary_classes.txt (1)

1-1: Excellent coverage of arbitrary value syntax.

This fixture thoroughly exercises the parser's handling of Tailwind's arbitrary value notation.

crates/biome_js_analyze/benches/fixtures/stress.txt (1)

1-1: Comprehensive stress test fixture.

The extensive class string provides thorough coverage of Tailwind's feature set. (Note: The static analysis hyphenation hint is a false positive—"only-child" is a standard CSS pseudo-class selector, not prose.)

crates/biome_js_analyze/benches/use_sorted_classes_parser.rs (3)

8-22: Platform-specific allocators correctly configured.

The allocator setup follows the established pattern from other benchmarks in the project.


24-27: Standard divan entry point.

Matches the pattern from tailwind_parser.rs.


29-47: Fixtures loaded at compile time.

Using include_str! is efficient and ensures the benchmark data is always available.

@codspeed-hq
Copy link

codspeed-hq bot commented Nov 9, 2025

CodSpeed Performance Report

Merging #7976 will not alter performance

Comparing dyc3/add-tw-bench (e37d41b) with main (f0612a5)

Summary

✅ 53 untouched
🆕 5 new
⏩ 85 skipped1

Benchmarks breakdown

Benchmark BASE HEAD Change
🆕 class_strings[arbitrary_classes] N/A 33.2 µs N/A
🆕 class_strings[extreme_stress] N/A 152 µs N/A
🆕 class_strings[simple_classes] N/A 20.2 µs N/A
🆕 class_strings[stress] N/A 375.7 µs N/A
🆕 class_strings[variant_classes] N/A 37.4 µs N/A

Footnotes

  1. 85 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@dyc3 dyc3 force-pushed the dyc3/add-tw-bench branch from cb2d699 to 1c8112d Compare November 9, 2025 10:11
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
crates/biome_tailwind_parser/benches/tailwind_parser.rs (1)

43-56: Consider failing loudly on missing fixtures.

Using unwrap_or_default() on line 47 will silently benchmark an empty string if the fixture file is missing or unreadable, producing misleading results. Consider using expect() to fail fast instead:

-    let code = std::fs::read_to_string(&path).unwrap_or_default();
+    let code = std::fs::read_to_string(&path)
+        .unwrap_or_else(|e| panic!("Failed to read fixture {}: {}", filename, e));

Apply the same fix to bench_cached at line 62.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d6d214 and 1c8112d.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock and included by **
📒 Files selected for processing (17)
  • .github/workflows/benchmark_tailwind.yml (1 hunks)
  • crates/biome_js_analyze/Cargo.toml (2 hunks)
  • crates/biome_js_analyze/benches/fixtures/arbitrary_classes.txt (1 hunks)
  • crates/biome_js_analyze/benches/fixtures/extreme_stress.txt (1 hunks)
  • crates/biome_js_analyze/benches/fixtures/simple_classes.txt (1 hunks)
  • crates/biome_js_analyze/benches/fixtures/stress.txt (1 hunks)
  • crates/biome_js_analyze/benches/fixtures/variant_classes.txt (1 hunks)
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs (1 hunks)
  • crates/biome_js_analyze/src/lint/nursery/use_sorted_classes.rs (1 hunks)
  • crates/biome_parser/src/lib.rs (3 hunks)
  • crates/biome_tailwind_parser/Cargo.toml (2 hunks)
  • crates/biome_tailwind_parser/benches/fixtures/arbitrary_classes.txt (1 hunks)
  • crates/biome_tailwind_parser/benches/fixtures/extreme_stress.txt (1 hunks)
  • crates/biome_tailwind_parser/benches/fixtures/simple_classes.txt (1 hunks)
  • crates/biome_tailwind_parser/benches/fixtures/stress.txt (1 hunks)
  • crates/biome_tailwind_parser/benches/fixtures/variant_classes.txt (1 hunks)
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • crates/biome_js_analyze/benches/fixtures/extreme_stress.txt
🚧 Files skipped from review as they are similar to previous changes (11)
  • crates/biome_js_analyze/Cargo.toml
  • crates/biome_js_analyze/benches/fixtures/variant_classes.txt
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_js_analyze/src/lint/nursery/use_sorted_classes.rs
  • crates/biome_tailwind_parser/Cargo.toml
  • crates/biome_tailwind_parser/benches/fixtures/arbitrary_classes.txt
  • crates/biome_js_analyze/benches/fixtures/simple_classes.txt
  • crates/biome_tailwind_parser/benches/fixtures/simple_classes.txt
  • crates/biome_js_analyze/benches/fixtures/arbitrary_classes.txt
  • crates/biome_tailwind_parser/benches/fixtures/variant_classes.txt
  • crates/biome_tailwind_parser/benches/fixtures/extreme_stress.txt
🧰 Additional context used
🧠 Learnings (17)
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Do not attempt to fix code; if a mandatory token/node is missing, return `None` instead

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : When a token is mandatory and present in the AST, use the AST-provided token (e.g., `node.l_paren_token().format()`) instead of emitting a static token

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : For non-mandatory tokens, use the provided helper constructors (e.g., `token`, `space_token`, `dynamic_token`)

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/xtask/codegen/*.ungram : Nodes for enclosing syntax errors must include the Bogus word (e.g., HtmlBogusAttribute)

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/**/*.rs : After generation, remove usages of `format_verbatim_node` and implement real formatting with biome_formatter utilities

Applied to files:

  • crates/biome_parser/src/lib.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Use `dbg_write!` to debug and inspect the emitted IR during formatting

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Import and use the `FormatNode` trait for AST nodes

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/crates/biome_*_{syntax,factory}/** : Create per-language crates biome_<lang>_syntax and biome_<lang>_factory under crates/

Applied to files:

  • crates/biome_parser/src/lib.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:25:05.698Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:25:05.698Z
Learning: Applies to crates/biome_service/../biome_lsp/src/server.tests.rs : Keep end-to-end LSP tests in ../biome_lsp/src/server.tests.rs

Applied to files:

  • crates/biome_parser/src/lib.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:21:24.116Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:21:24.116Z
Learning: Prefer implementing the Diagnostic trait via `#[derive(Diagnostic)]`

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/spec_tests.rs : In tests/spec_tests.rs, generate tests with `tests_macros::gen_tests! {"tests/specs/html/**/*.html", crate::spec_test::run, ""}`

Applied to files:

  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/** : Create a tests directory containing a specs subfolder and the files spec_test.rs, spec_tests.rs, and language.rs

Applied to files:

  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:25:05.698Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:25:05.698Z
Learning: Applies to crates/biome_service/src/workspace/watcher.tests.rs : Place watcher tests related to workspace methods in src/workspace/watcher.tests.rs

Applied to files:

  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/language.rs : Create tests/language.rs defining `HtmlTestFormatLanguage` and implement the TestFormatLanguage trait

Applied to files:

  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/lib.rs : Add the provided AsFormat, IntoFormat, and iterator plumbing code to lib.rs

Applied to files:

  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/crates/**/src/lexer/mod.rs : Create a lexer module at crates/<parser_crate>/src/lexer/mod.rs

Applied to files:

  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/xtask/codegen/src/*_kinds_src.rs : Add src/<lang>_kinds_src.rs under xtask/codegen that returns a static KindSrc

Applied to files:

  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
🧬 Code graph analysis (2)
crates/biome_parser/src/lib.rs (5)
crates/biome_js_parser/src/parser.rs (1)
  • source (165-167)
crates/biome_html_parser/src/parser.rs (1)
  • source (90-92)
crates/biome_tailwind_parser/src/parser.rs (1)
  • source (66-68)
crates/biome_html_parser/src/token_source.rs (1)
  • current_range (170-172)
crates/biome_tailwind_parser/src/token_source.rs (1)
  • current_range (115-117)
crates/biome_tailwind_parser/benches/tailwind_parser.rs (1)
crates/biome_tailwind_parser/src/lib.rs (2)
  • parse_tailwind (28-31)
  • parse_tailwind_with_cache (15-27)
🪛 actionlint (1.7.8)
.github/workflows/benchmark_tailwind.yml

36-36: label "depot-ubuntu-24.04-arm-16" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2025", "windows-2022", "windows-11-arm", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-26-xlarge", "macos-26", "macos-15-intel", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)

🪛 LanguageTool
crates/biome_js_analyze/benches/fixtures/stress.txt

[uncategorized] ~1-~1: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...t-slate-600 only-of-type:text-slate-500 only-child:text-slate-400 checked:bg-blue-500 chec...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

crates/biome_tailwind_parser/benches/fixtures/stress.txt

[uncategorized] ~1-~1: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...t-slate-600 only-of-type:text-slate-500 only-child:text-slate-400 checked:bg-blue-500 chec...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (22)
  • GitHub Check: Bench (biome_package)
  • GitHub Check: Documentation
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: Test (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Test Node.js API
  • GitHub Check: Check Dependencies
  • GitHub Check: Lint project (depot-windows-2022)
  • GitHub Check: Bench (biome_graphql_formatter)
  • GitHub Check: Bench (biome_configuration)
  • GitHub Check: Bench (biome_graphql_parser)
  • GitHub Check: Bench (biome_tailwind_parser)
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: Bench (biome_module_graph)
  • GitHub Check: Bench (biome_css_parser)
  • GitHub Check: Bench (biome_js_formatter)
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Bench (biome_css_formatter)
  • GitHub Check: Bench (biome_css_analyze)
  • GitHub Check: autofix
  • GitHub Check: Bench (biome_json_formatter)
  • GitHub Check: Bench (biome_json_parser)
  • GitHub Check: Bench (biome_json_analyze)
🔇 Additional comments (8)
crates/biome_js_analyze/benches/fixtures/stress.txt (1)

1-1: Solid stress test fixture.

This provides comprehensive coverage across standard utilities, responsive variants, pseudo-classes, state modifiers, and arbitrary values—all in a single long line that should exercise the lexer and parser well. The length and density are well-suited to benchmarking.

crates/biome_parser/src/lib.rs (3)

250-262: LGTM! Improved diagnostic precision.

Adding the token range to assertion messages will make debugging parser issues much easier. The change is applied consistently and correctly.


265-276: LGTM! Consistent diagnostic improvement.

The same helpful range information added here as in bump, maintaining consistency across assertion messages.


325-343: LGTM! Completes the consistent pattern.

All three assertion methods now provide the same level of diagnostic detail, which will aid debugging across the parser.

.github/workflows/benchmark_tailwind.yml (1)

36-36: Verify the custom runner label.

The runner depot-ubuntu-24.04-arm-16 isn't a standard GitHub-hosted runner. Confirm this is the intended Depot or self-hosted runner for your infrastructure.

crates/biome_tailwind_parser/benches/fixtures/stress.txt (1)

1-1: LGTM!

Fixture file serves its purpose as a stress test with an extensive collection of Tailwind classes. The LanguageTool hyphenation hint can be safely ignored—these are CSS class names, not prose.

crates/biome_tailwind_parser/benches/tailwind_parser.rs (2)

1-24: Nice benchmark setup!

The platform-specific allocator configuration and divan integration look solid. The CI workflow you've added addresses the previous concern about benchmark execution.


58-75: Cache warming strategy looks good.

The explicit warm-up parse before benchmarking cached performance is the right approach and well-documented.

@dyc3 dyc3 force-pushed the dyc3/add-tw-bench branch from 2ea2e4c to aababc2 Compare November 9, 2025 11:44
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
crates/biome_js_analyze/src/lint/nursery/use_sorted_classes.rs (1)

3-3: Consider restricting visibility to pub(crate).

Since the benchmark is within the same crate (biome_js_analyze), pub(crate) would be more appropriate than pub. This limits the API surface whilst still allowing your benchmarks to access the tokeniser.

Apply this diff:

-pub mod class_lexer;
+pub(crate) mod class_lexer;
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2ea2e4c and aababc2.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock and included by **
📒 Files selected for processing (17)
  • .github/workflows/benchmark_tailwind.yml (1 hunks)
  • crates/biome_js_analyze/Cargo.toml (2 hunks)
  • crates/biome_js_analyze/benches/fixtures/arbitrary_classes.txt (1 hunks)
  • crates/biome_js_analyze/benches/fixtures/extreme_stress.txt (1 hunks)
  • crates/biome_js_analyze/benches/fixtures/simple_classes.txt (1 hunks)
  • crates/biome_js_analyze/benches/fixtures/stress.txt (1 hunks)
  • crates/biome_js_analyze/benches/fixtures/variant_classes.txt (1 hunks)
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs (1 hunks)
  • crates/biome_js_analyze/src/lint/nursery/use_sorted_classes.rs (1 hunks)
  • crates/biome_parser/src/lib.rs (3 hunks)
  • crates/biome_tailwind_parser/Cargo.toml (2 hunks)
  • crates/biome_tailwind_parser/benches/fixtures/arbitrary_classes.txt (1 hunks)
  • crates/biome_tailwind_parser/benches/fixtures/extreme_stress.txt (1 hunks)
  • crates/biome_tailwind_parser/benches/fixtures/simple_classes.txt (1 hunks)
  • crates/biome_tailwind_parser/benches/fixtures/stress.txt (1 hunks)
  • crates/biome_tailwind_parser/benches/fixtures/variant_classes.txt (1 hunks)
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • crates/biome_js_analyze/benches/fixtures/variant_classes.txt
🚧 Files skipped from review as they are similar to previous changes (9)
  • crates/biome_tailwind_parser/benches/fixtures/extreme_stress.txt
  • crates/biome_tailwind_parser/Cargo.toml
  • crates/biome_js_analyze/benches/fixtures/extreme_stress.txt
  • crates/biome_tailwind_parser/benches/fixtures/simple_classes.txt
  • crates/biome_js_analyze/Cargo.toml
  • crates/biome_js_analyze/benches/fixtures/arbitrary_classes.txt
  • crates/biome_js_analyze/benches/fixtures/simple_classes.txt
  • crates/biome_tailwind_parser/benches/fixtures/arbitrary_classes.txt
  • crates/biome_tailwind_parser/benches/fixtures/variant_classes.txt
🧰 Additional context used
🧠 Learnings (19)
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Do not attempt to fix code; if a mandatory token/node is missing, return `None` instead

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : When a token is mandatory and present in the AST, use the AST-provided token (e.g., `node.l_paren_token().format()`) instead of emitting a static token

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : For non-mandatory tokens, use the provided helper constructors (e.g., `token`, `space_token`, `dynamic_token`)

Applied to files:

  • crates/biome_parser/src/lib.rs
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/**/*.rs : After generation, remove usages of `format_verbatim_node` and implement real formatting with biome_formatter utilities

Applied to files:

  • crates/biome_parser/src/lib.rs
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/xtask/codegen/*.ungram : Nodes for enclosing syntax errors must include the Bogus word (e.g., HtmlBogusAttribute)

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Import and use the `FormatNode` trait for AST nodes

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Use `dbg_write!` to debug and inspect the emitted IR during formatting

Applied to files:

  • crates/biome_parser/src/lib.rs
📚 Learning: 2025-10-15T09:25:05.698Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:25:05.698Z
Learning: Applies to crates/biome_service/../biome_lsp/src/server.tests.rs : Keep end-to-end LSP tests in ../biome_lsp/src/server.tests.rs

Applied to files:

  • crates/biome_parser/src/lib.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/crates/biome_*_{syntax,factory}/** : Create per-language crates biome_<lang>_syntax and biome_<lang>_factory under crates/

Applied to files:

  • crates/biome_parser/src/lib.rs
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/language.rs : Create tests/language.rs defining `HtmlTestFormatLanguage` and implement the TestFormatLanguage trait

Applied to files:

  • crates/biome_parser/src/lib.rs
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/crates/**/src/lexer/mod.rs : Create a lexer module at crates/<parser_crate>/src/lexer/mod.rs

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/use_sorted_classes.rs
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:23:33.055Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:23:33.055Z
Learning: Applies to crates/biome_js_type_info/src/{type_info,local_inference,resolver,flattening}.rs : Avoid recursive type structures and cross-module Arcs; represent links between types using TypeReference and TypeData::Reference.

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/use_sorted_classes.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Lexer must implement the biome_parser::Lexer trait

Applied to files:

  • crates/biome_js_analyze/src/lint/nursery/use_sorted_classes.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/xtask/codegen/src/*_kinds_src.rs : Add src/<lang>_kinds_src.rs under xtask/codegen that returns a static KindSrc

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/** : Create a tests directory containing a specs subfolder and the files spec_test.rs, spec_tests.rs, and language.rs

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/spec_tests.rs : In tests/spec_tests.rs, generate tests with `tests_macros::gen_tests! {"tests/specs/html/**/*.html", crate::spec_test::run, ""}`

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/lib.rs : Add the provided AsFormat, IntoFormat, and iterator plumbing code to lib.rs

Applied to files:

  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:25:05.698Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:25:05.698Z
Learning: Applies to crates/biome_service/src/workspace/watcher.tests.rs : Place watcher tests related to workspace methods in src/workspace/watcher.tests.rs

Applied to files:

  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:23:33.055Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:23:33.055Z
Learning: Applies to crates/biome_js_type_info/biome_module_graph/src/**/*.rs : Do not copy or clone data between module graph entries (including behind Arc). Each module must avoid holding duplicated data from another module to enable simple invalidation.

Applied to files:

  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
🧬 Code graph analysis (2)
crates/biome_parser/src/lib.rs (5)
crates/biome_js_parser/src/parser.rs (1)
  • source (165-167)
crates/biome_html_parser/src/parser.rs (1)
  • source (90-92)
crates/biome_tailwind_parser/src/parser.rs (1)
  • source (66-68)
crates/biome_html_parser/src/token_source.rs (1)
  • current_range (170-172)
crates/biome_tailwind_parser/src/token_source.rs (1)
  • current_range (115-117)
crates/biome_tailwind_parser/benches/tailwind_parser.rs (1)
crates/biome_tailwind_parser/src/lib.rs (2)
  • parse_tailwind (28-31)
  • parse_tailwind_with_cache (15-27)
🪛 actionlint (1.7.8)
.github/workflows/benchmark_tailwind.yml

36-36: label "depot-ubuntu-24.04-arm-16" is unknown. available labels are "windows-latest", "windows-latest-8-cores", "windows-2025", "windows-2022", "windows-11-arm", "ubuntu-latest", "ubuntu-latest-4-cores", "ubuntu-latest-8-cores", "ubuntu-latest-16-cores", "ubuntu-24.04", "ubuntu-24.04-arm", "ubuntu-22.04", "ubuntu-22.04-arm", "macos-latest", "macos-latest-xl", "macos-latest-xlarge", "macos-latest-large", "macos-26-xlarge", "macos-26", "macos-15-intel", "macos-15-xlarge", "macos-15-large", "macos-15", "macos-14-xl", "macos-14-xlarge", "macos-14-large", "macos-14", "macos-13-xl", "macos-13-xlarge", "macos-13-large", "macos-13", "self-hosted", "x64", "arm", "arm64", "linux", "macos", "windows". if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file

(runner-label)

🪛 LanguageTool
crates/biome_js_analyze/benches/fixtures/stress.txt

[uncategorized] ~1-~1: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...t-slate-600 only-of-type:text-slate-500 only-child:text-slate-400 checked:bg-blue-500 chec...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

crates/biome_tailwind_parser/benches/fixtures/stress.txt

[uncategorized] ~1-~1: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...t-slate-600 only-of-type:text-slate-500 only-child:text-slate-400 checked:bg-blue-500 chec...

(HYPHENATED_LY_ADVERB_ADJECTIVE)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (23)
  • GitHub Check: Test Node.js API
  • GitHub Check: Documentation
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: Test (depot-ubuntu-24.04-arm-16)
  • GitHub Check: End-to-end tests
  • GitHub Check: Lint project (depot-windows-2022)
  • GitHub Check: Check Dependencies
  • GitHub Check: Bench (biome_tailwind_parser)
  • GitHub Check: Bench (biome_json_analyze)
  • GitHub Check: Bench (biome_json_formatter)
  • GitHub Check: Bench (biome_css_formatter)
  • GitHub Check: Bench (biome_json_parser)
  • GitHub Check: Bench (biome_module_graph)
  • GitHub Check: Bench (biome_css_parser)
  • GitHub Check: Bench (biome_css_analyze)
  • GitHub Check: Bench (biome_graphql_formatter)
  • GitHub Check: Bench (biome_graphql_parser)
  • GitHub Check: autofix
  • GitHub Check: Bench (biome_configuration)
  • GitHub Check: Bench (biome_js_formatter)
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Bench (biome_package)
🔇 Additional comments (5)
crates/biome_parser/src/lib.rs (1)

250-343: LGTM! Improved assertion messages for parser debugging.

Adding the token range to the assertion messages in bump, bump_ts, and bump_with_context will make debugging parser issues much easier. The implementation is consistent across all three methods.

.github/workflows/benchmark_tailwind.yml (2)

1-26: LGTM! Well-configured workflow triggers.

The triggers and path filters are appropriate for a Tailwind benchmarking workflow, targeting the relevant crates whilst avoiding unnecessary runs.


30-69: LGTM! Solid benchmark job configuration.

The workflow is well-structured with appropriate timeouts and OOM mitigation. The actionlint warning about the runner label is a false positive—depot-ubuntu-24.04-arm-16 is a custom Depot runner, which is intentional.

crates/biome_js_analyze/benches/fixtures/stress.txt (1)

1-1: LGTM! Benchmark fixture is appropriate.

The extensive Tailwind class string serves well as stress-test data for the parser. The static analysis hint about hyphenation is a false positive—only-child: is valid Tailwind pseudo-class syntax, not English prose.

crates/biome_js_analyze/benches/use_sorted_classes_parser.rs (1)

1-66: LGTM! Well-structured benchmark.

The benchmark is cleanly implemented:

  • Platform-specific allocator setup follows standard patterns
  • Fixture loading via include_str! is appropriate
  • Correct use of black_box to prevent compiler optimisations
  • Throughput measurement by bytes provides useful metrics

The use of Criterion (rather than divan) aligns with the discussion in the PR comments—both tools are acceptable whilst some capabilities remain divan-exclusive.

@dyc3 dyc3 force-pushed the dyc3/add-tw-bench branch from 1a6ae8e to f0c3b78 Compare November 9, 2025 11:57
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
crates/biome_js_analyze/benches/use_sorted_classes_parser.rs (2)

16-18: Consider removing the redundant System allocator declaration.

Rust uses the system allocator by default when no #[global_allocator] is specified, so this declaration is redundant. However, the explicit comment does document the platform limitation clearly.


20-21: Clarify the "ported from divan" comment.

The comment suggests this benchmark was converted from divan to criterion, but the PR context indicates it may have been written fresh or the conversion story is more nuanced. Consider updating the comment to reflect the actual history or simply describe what the benchmark does.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a6ae8e and f0c3b78.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock and included by **
📒 Files selected for processing (4)
  • crates/biome_js_analyze/Cargo.toml (2 hunks)
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs (1 hunks)
  • crates/biome_tailwind_parser/Cargo.toml (2 hunks)
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
🧰 Additional context used
🧠 Learnings (14)
📓 Common learnings
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/crates/biome_*_{syntax,factory}/** : Create per-language crates biome_<lang>_syntax and biome_<lang>_factory under crates/
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:25:05.698Z
Learning: Applies to crates/biome_service/../biome_lsp/src/server.tests.rs : Keep end-to-end LSP tests in ../biome_lsp/src/server.tests.rs
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/spec_tests.rs : In tests/spec_tests.rs, generate tests with `tests_macros::gen_tests! {"tests/specs/html/**/*.html", crate::spec_test::run, ""}`
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/**/*.rs : After generation, remove usages of `format_verbatim_node` and implement real formatting with biome_formatter utilities
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/language.rs : Create tests/language.rs defining `HtmlTestFormatLanguage` and implement the TestFormatLanguage trait
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/**/Cargo.toml : Add the specified dev-dependencies under [dev-dependencies] for the test infrastructure

Applied to files:

  • crates/biome_tailwind_parser/Cargo.toml
  • crates/biome_js_analyze/Cargo.toml
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/Cargo.toml : Declare the dependency `biome_js_formatter = { version = "0.0.1", path = "../biome_js_formatter" }` for internal installation

Applied to files:

  • crates/biome_tailwind_parser/Cargo.toml
  • crates/biome_js_analyze/Cargo.toml
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/**/*.rs : After generation, remove usages of `format_verbatim_node` and implement real formatting with biome_formatter utilities

Applied to files:

  • crates/biome_tailwind_parser/Cargo.toml
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_js_analyze/Cargo.toml
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/crates/biome_*_{syntax,factory}/** : Create per-language crates biome_<lang>_syntax and biome_<lang>_factory under crates/

Applied to files:

  • crates/biome_tailwind_parser/Cargo.toml
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_js_analyze/Cargo.toml
📚 Learning: 2025-10-15T09:20:45.587Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_aria_metadata/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:20:45.587Z
Learning: Applies to crates/biome_aria_metadata/**/{build.rs,aria-data.json} : Keep aria-data.json at the expected location/name because build.rs uses it to generate ARIA metadata

Applied to files:

  • crates/biome_tailwind_parser/Cargo.toml
📚 Learning: 2025-10-15T09:25:05.698Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:25:05.698Z
Learning: Applies to crates/biome_service/../biome_lsp/src/server.tests.rs : Keep end-to-end LSP tests in ../biome_lsp/src/server.tests.rs

Applied to files:

  • crates/biome_tailwind_parser/Cargo.toml
  • crates/biome_js_analyze/Cargo.toml
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : For non-mandatory tokens, use the provided helper constructors (e.g., `token`, `space_token`, `dynamic_token`)

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/crates/**/src/lexer/mod.rs : Create a lexer module at crates/<parser_crate>/src/lexer/mod.rs

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/language.rs : Create tests/language.rs defining `HtmlTestFormatLanguage` and implement the TestFormatLanguage trait

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/spec_tests.rs : In tests/spec_tests.rs, generate tests with `tests_macros::gen_tests! {"tests/specs/html/**/*.html", crate::spec_test::run, ""}`

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_js_analyze/Cargo.toml
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/** : Create a tests directory containing a specs subfolder and the files spec_test.rs, spec_tests.rs, and language.rs

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/xtask/codegen/src/*_kinds_src.rs : Add src/<lang>_kinds_src.rs under xtask/codegen that returns a static KindSrc

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
📚 Learning: 2025-10-15T09:25:05.698Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:25:05.698Z
Learning: Applies to crates/biome_service/src/workspace/watcher.tests.rs : Place watcher tests related to workspace methods in src/workspace/watcher.tests.rs

Applied to files:

  • crates/biome_js_analyze/Cargo.toml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (24)
  • GitHub Check: End-to-end tests
  • GitHub Check: Documentation
  • GitHub Check: Test (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Test (depot-windows-2022-16)
  • GitHub Check: Lint project (depot-windows-2022)
  • GitHub Check: Check Dependencies
  • GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
  • GitHub Check: Test Node.js API
  • GitHub Check: Bench (biome_css_formatter)
  • GitHub Check: Bench (biome_graphql_formatter)
  • GitHub Check: Bench (biome_tailwind_parser)
  • GitHub Check: Bench (biome_css_analyze)
  • GitHub Check: Bench (biome_css_parser)
  • GitHub Check: Bench (biome_graphql_parser)
  • GitHub Check: Bench (biome_module_graph)
  • GitHub Check: Bench (biome_configuration)
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Bench (biome_js_formatter)
  • GitHub Check: autofix
  • GitHub Check: Bench (biome_package)
  • GitHub Check: Bench (biome_json_formatter)
  • GitHub Check: Bench (biome_json_analyze)
  • GitHub Check: Bench (biome_json_parser)
🔇 Additional comments (5)
crates/biome_tailwind_parser/Cargo.toml (3)

29-31: Verify that codspeed-criterion-compat is the intended benchmarking framework.

The changes switch criterion to use the codspeed-criterion-compat compatibility layer. Given the PR comments mention the project has switched to divan, please confirm this is intentional and aligns with the CodSpeed CI workflow mentioned in the AI summary. If divan is now the standard, consider whether this should use divan instead.

Also applies to: 35-35


40-41: Verify allocator condition consistency.

The conditional for tikv-jemallocator excludes aarch64 musl targets. Ensure this condition is consistent with how other benchmarks in the project configure platform-specific allocators. If this pattern is new, confirm it's the right approach.


43-45: Benchmark configuration looks good.

The [[bench]] configuration with harness = false is correct for custom benchmark harnesses, and aligns with the new benches/tailwind_parser.rs mentioned in the summary.

crates/biome_js_analyze/Cargo.toml (1)

57-79: LGTM!

The bench target is correctly configured with harness = false, and the codspeed-criterion-compat dependency aligns with the project's benchmarking setup.

crates/biome_js_analyze/benches/use_sorted_classes_parser.rs (1)

42-63: LGTM!

The benchmark correctly uses black_box to prevent optimisations and follows standard criterion patterns. The throughput metric (total fixture bytes) is reasonable for comparing processing speed across runs, even though it includes whitespace.

codspeed compat with divan wouldn't let me use byte counters for measuring throughput
@dyc3 dyc3 force-pushed the dyc3/add-tw-bench branch from 0253184 to e37d41b Compare November 9, 2025 12:05
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
crates/biome_tailwind_parser/benches/tailwind_parser.rs (1)

24-42: Consider failing loudly if no fixtures are loaded.

If read_dir() fails (e.g., directory doesn't exist), the function silently returns an empty Vec, and the benchmark will run with nothing to measure. Whilst this might be caught during development, an explicit check could save time debugging.

You could add a check after loading fixtures:

    fixtures
+    .tap(|f| assert!(!f.is_empty(), "No fixtures found in {}", fixtures_dir.display()))
}

Or simply expect() the read_dir() call if you prefer a harder failure mode.

crates/biome_js_analyze/benches/use_sorted_classes_parser.rs (1)

49-58: Pre-split classes outside the hot loop

We're paying for split_whitespace every sample, so the benchmark mixes string-splitting time with the lexer cost. Hoist the split once per fixture (e.g. collect into a Vec captured by a move closure, or use iter_batched_ref) so the inner loop only measures tokenize_class. Keeps the numbers focused on the parser.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0c3b78 and e37d41b.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock and included by **
📒 Files selected for processing (4)
  • crates/biome_js_analyze/Cargo.toml (2 hunks)
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs (1 hunks)
  • crates/biome_tailwind_parser/Cargo.toml (2 hunks)
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs (1 hunks)
🧰 Additional context used
🧠 Learnings (18)
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/**/Cargo.toml : Add the specified dev-dependencies under [dev-dependencies] for the test infrastructure

Applied to files:

  • crates/biome_js_analyze/Cargo.toml
  • crates/biome_tailwind_parser/Cargo.toml
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/Cargo.toml : Declare the dependency `biome_js_formatter = { version = "0.0.1", path = "../biome_js_formatter" }` for internal installation

Applied to files:

  • crates/biome_js_analyze/Cargo.toml
  • crates/biome_tailwind_parser/Cargo.toml
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/**/*.rs : After generation, remove usages of `format_verbatim_node` and implement real formatting with biome_formatter utilities

Applied to files:

  • crates/biome_js_analyze/Cargo.toml
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
  • crates/biome_tailwind_parser/Cargo.toml
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Import and use the `FormatNode` trait for AST nodes

Applied to files:

  • crates/biome_js_analyze/Cargo.toml
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/crates/biome_*_{syntax,factory}/** : Create per-language crates biome_<lang>_syntax and biome_<lang>_factory under crates/

Applied to files:

  • crates/biome_js_analyze/Cargo.toml
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
  • crates/biome_tailwind_parser/Cargo.toml
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/spec_tests.rs : In tests/spec_tests.rs, generate tests with `tests_macros::gen_tests! {"tests/specs/html/**/*.html", crate::spec_test::run, ""}`

Applied to files:

  • crates/biome_js_analyze/Cargo.toml
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
  • crates/biome_tailwind_parser/Cargo.toml
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Use `dbg_write!` to debug and inspect the emitted IR during formatting

Applied to files:

  • crates/biome_js_analyze/Cargo.toml
📚 Learning: 2025-10-15T09:25:05.698Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:25:05.698Z
Learning: Applies to crates/biome_service/../biome_lsp/src/server.tests.rs : Keep end-to-end LSP tests in ../biome_lsp/src/server.tests.rs

Applied to files:

  • crates/biome_js_analyze/Cargo.toml
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
  • crates/biome_tailwind_parser/Cargo.toml
📚 Learning: 2025-10-15T09:23:33.055Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:23:33.055Z
Learning: Applies to crates/biome_js_type_info/src/{type_info,local_inference,resolver,flattening}.rs : Avoid recursive type structures and cross-module Arcs; represent links between types using TypeReference and TypeData::Reference.

Applied to files:

  • crates/biome_js_analyze/Cargo.toml
📚 Learning: 2025-10-15T09:23:33.055Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:23:33.055Z
Learning: Applies to crates/biome_js_type_info/src/type_info.rs : Add new TypeScript type support by extending the TypeData enum rather than introducing parallel structures.

Applied to files:

  • crates/biome_js_analyze/Cargo.toml
📚 Learning: 2025-10-15T09:25:05.698Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:25:05.698Z
Learning: Applies to crates/biome_service/src/workspace/watcher.tests.rs : Place watcher tests related to workspace methods in src/workspace/watcher.tests.rs

Applied to files:

  • crates/biome_js_analyze/Cargo.toml
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/** : Create a tests directory containing a specs subfolder and the files spec_test.rs, spec_tests.rs, and language.rs

Applied to files:

  • crates/biome_js_analyze/Cargo.toml
  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:25:05.698Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:25:05.698Z
Learning: Applies to crates/biome_service/src/workspace.rs : Implement and expose the Workspace trait in src/workspace.rs

Applied to files:

  • crates/biome_js_analyze/Cargo.toml
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : For non-mandatory tokens, use the provided helper constructors (e.g., `token`, `space_token`, `dynamic_token`)

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/crates/**/src/lexer/mod.rs : Create a lexer module at crates/<parser_crate>/src/lexer/mod.rs

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:24:31.042Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:24:31.042Z
Learning: Applies to crates/biome_parser/xtask/codegen/src/*_kinds_src.rs : Add src/<lang>_kinds_src.rs under xtask/codegen that returns a static KindSrc

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/language.rs : Create tests/language.rs defining `HtmlTestFormatLanguage` and implement the TestFormatLanguage trait

Applied to files:

  • crates/biome_js_analyze/benches/use_sorted_classes_parser.rs
  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/lib.rs : Add the provided AsFormat, IntoFormat, and iterator plumbing code to lib.rs

Applied to files:

  • crates/biome_tailwind_parser/benches/tailwind_parser.rs
🧬 Code graph analysis (1)
crates/biome_tailwind_parser/benches/tailwind_parser.rs (1)
crates/biome_tailwind_parser/src/lib.rs (2)
  • parse_tailwind (28-31)
  • parse_tailwind_with_cache (15-27)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (17)
  • GitHub Check: Test Node.js API
  • GitHub Check: autofix
  • GitHub Check: Bench (biome_module_graph)
  • GitHub Check: Bench (biome_js_analyze)
  • GitHub Check: Bench (biome_tailwind_parser)
  • GitHub Check: Bench (biome_js_parser)
  • GitHub Check: Bench (biome_js_formatter)
  • GitHub Check: Bench (biome_graphql_formatter)
  • GitHub Check: Bench (biome_json_analyze)
  • GitHub Check: Bench (biome_configuration)
  • GitHub Check: Bench (biome_json_formatter)
  • GitHub Check: Bench (biome_json_parser)
  • GitHub Check: Bench (biome_package)
  • GitHub Check: Bench (biome_css_formatter)
  • GitHub Check: Bench (biome_css_analyze)
  • GitHub Check: Bench (biome_css_parser)
  • GitHub Check: Bench (biome_graphql_parser)
🔇 Additional comments (7)
crates/biome_tailwind_parser/benches/tailwind_parser.rs (3)

8-22: LGTM!

The platform-specific allocator configuration follows the standard pattern for Rust benchmarking. The musl/aarch64 fallback to system allocator is a sensible workaround.


44-74: LGTM!

The benchmark logic is well-structured. Proper use of black_box prevents compiler optimisations from skewing results, the cache warm-up is correctly placed outside the measurement loop, and throughput measurement by bytes provides meaningful performance metrics.


76-77: LGTM!

Standard Criterion boilerplate—nothing to see here, move along! 🐰

crates/biome_tailwind_parser/Cargo.toml (3)

31-31: LGTM!

Using codspeed-criterion-compat as a drop-in replacement for Criterion is the standard approach for CodSpeed integration. The exact version pin ensures reproducible benchmark results.


40-41: LGTM!

The target-specific jemalloc dependency matches the conditional allocator setup in the benchmark file. Excluding aarch64/musl is the right call, as noted in the benchmark comments.


43-45: LGTM!

The bench declaration is correct. harness = false lets Criterion provide its own harness, and the name matches the benchmark module.

crates/biome_js_analyze/Cargo.toml (1)

73-79: Bench target wiring looks right

Harness=false plus the extra bench target is exactly what Criterion expects; thanks for threading it through.

Copy link
Contributor Author

dyc3 commented Nov 9, 2025

Merge activity

  • Nov 9, 12:36 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Nov 9, 12:37 PM UTC: @dyc3 merged this pull request with Graphite.

@dyc3 dyc3 merged commit ac3fc64 into main Nov 9, 2025
30 checks passed
@dyc3 dyc3 deleted the dyc3/add-tw-bench branch November 9, 2025 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Linter Area: linter A-Parser Area: parser L-JavaScript Language: JavaScript and super languages L-Tailwind Language: Tailwind CSS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants