Conversation
🦋 Changeset detectedLatest commit: c2c8aea The changes in this PR will be included in the next version bump. This PR includes changesets to release 13 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughAdds a new JavaScript lint rule Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Implement nursery rule that enforces the use of `u` or `v` flag for regular expressions. Equivalent to ESLint's `require-unicode-regexp`. Closes biomejs#8739
e6e3bdf to
c2c8aea
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@crates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs`:
- Around line 178-184: Replacing the flags token with
JsSyntaxToken::new_detached(..., [], [],) drops the original token's
leading/trailing trivia (comments/whitespace); when creating the new token for
JsSyntaxKind::JS_STRING_LITERAL with new_flags, capture and pass the original
token's trivia into new_detached (e.g., use the token's leading and trailing
trivia accessors) and then call mutation.replace_token(token, new_token) so
comments/whitespace are preserved.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (8)
crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rsis excluded by!**/migrate/eslint_any_rule_to_biome.rsand included by**crates/biome_configuration/src/analyzer/linter/rules.rsis excluded by!**/rules.rsand included by**crates/biome_diagnostics_categories/src/categories.rsis excluded by!**/categories.rsand included by**crates/biome_js_analyze/src/lint/nursery.rsis excluded by!**/nursery.rsand included by**crates/biome_js_analyze/tests/specs/nursery/useUnicodeRegex/invalid.js.snapis excluded by!**/*.snapand included by**crates/biome_js_analyze/tests/specs/nursery/useUnicodeRegex/valid.js.snapis excluded by!**/*.snapand included by**packages/@biomejs/backend-jsonrpc/src/workspace.tsis excluded by!**/backend-jsonrpc/src/workspace.tsand included by**packages/@biomejs/biome/configuration_schema.jsonis excluded by!**/configuration_schema.jsonand included by**
📒 Files selected for processing (6)
.changeset/use-unicode-regex-rule.mdcrates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rscrates/biome_js_analyze/tests/specs/nursery/useUnicodeRegex/invalid.jscrates/biome_js_analyze/tests/specs/nursery/useUnicodeRegex/valid.jscrates/biome_rule_options/src/lib.rscrates/biome_rule_options/src/use_unicode_regex.rs
🚧 Files skipped from review as they are similar to previous changes (1)
- crates/biome_rule_options/src/lib.rs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.rs: Use inline rustdoc documentation for rules, assists, and their options
Use thedbg!()macro for debugging output in Rust tests and code
Use doc tests (doctest) format with code blocks in rustdoc comments; ensure assertions pass in tests
Files:
crates/biome_rule_options/src/use_unicode_regex.rscrates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs
🧠 Learnings (26)
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/biome_rule_options/lib/**/*.rs : Apply `#[serde(deny_unknown_fields)]` to rule option structs to enforce strict configuration validation
Applied to files:
crates/biome_rule_options/src/use_unicode_regex.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/biome_rule_options/lib/**/*.rs : Use `Option<_>` wrapper for rule option fields to enable proper merging of configurations
Applied to files:
crates/biome_rule_options/src/use_unicode_regex.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/biome_rule_options/lib/**/*.rs : Apply `#[serde(rename_all = "camelCase")]` to rule option structs to match JSON configuration naming convention
Applied to files:
crates/biome_rule_options/src/use_unicode_regex.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/biome_rule_options/lib/**/*.rs : Rule option types must derive `Deserializable`, `Serialize`, `Deserialize`, and optionally `JsonSchema` traits
Applied to files:
crates/biome_rule_options/src/use_unicode_regex.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/biome_rule_options/lib/**/*.rs : Rule options must be defined in the `biome_rule_options` crate with a file named after the rule
Applied to files:
crates/biome_rule_options/src/use_unicode_regex.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/biome_rule_options/lib/**/*.rs : Implement `biome_deserialize::Merge` for rule option types to define how shared and user configurations are merged
Applied to files:
crates/biome_rule_options/src/use_unicode_regex.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/biome_rule_options/lib/**/*.rs : Use `Box<[Box<str>]>` instead of `Vec<String>` for collections of strings in rule options to save memory
Applied to files:
crates/biome_rule_options/src/use_unicode_regex.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/language_kind.rs : Add a new variant to `LanguageKind` enum in `language_kind.rs` file and implement all methods for the new language variant
Applied to files:
crates/biome_rule_options/src/use_unicode_regex.rs
📚 Learning: 2025-12-21T21:15:03.796Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T21:15:03.796Z
Learning: Applies to **/*.rs : Use inline rustdoc documentation for rules, assists, and their options
Applied to files:
crates/biome_rule_options/src/use_unicode_regex.rs
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : Use `TypeData::Unknown` to indicate when type inference falls short or is not implemented
Applied to files:
crates/biome_rule_options/src/use_unicode_regex.rs
📚 Learning: 2025-12-21T21:15:03.796Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T21:15:03.796Z
Learning: For new lint rules in changesets, show an example of invalid case in inline code or code block
Applied to files:
.changeset/use-unicode-regex-rule.md
📚 Learning: 2025-12-21T21:15:03.796Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T21:15:03.796Z
Learning: For rule changes in changesets, clearly demonstrate what is now invalid that wasn't before, or vice versa
Applied to files:
.changeset/use-unicode-regex-rule.md
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Rule names should use the `use` prefix when the rule's sole intention is to mandate a single concept
Applied to files:
crates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `declare_lint_rule!` macro with a `version` field set to `next` for new rules
Applied to files:
crates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : When porting rules from other linters, use `sources` metadata with `RuleSource::Eslint().same()` for identical behavior or `.inspired()` for different behavior
Applied to files:
crates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs
📚 Learning: 2025-12-22T09:26:56.943Z
Learnt from: ematipico
Repo: biomejs/biome PR: 8537
File: crates/biome_js_analyze/src/lint/nursery/no_leaked_render.rs:167-210
Timestamp: 2025-12-22T09:26:56.943Z
Learning: When defining lint rules (declare_lint_rule!), only specify fix_kind if the rule implements an action(...) function. Rules that only emit diagnostics without a code fix should omit fix_kind. This applies to all Rust lint rule definitions under crates/.../src/lint (e.g., crates/biome_js_analyze/src/lint/...).
Applied to files:
crates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Implement the `action` function and add `fix_kind` metadata to the rule macro if the rule provides code actions
Applied to files:
crates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use `declare_node_union!` macro to query multiple node types together to avoid redundant traversal passes
Applied to files:
crates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Deprecated rules must include a `deprecated` field in the `declare_lint_rule!` macro with an explanation of what rule to use instead
Applied to files:
crates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : New rules must be placed inside the `nursery` group before promotion to other groups
Applied to files:
crates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Mark rules with `issue_number` in the `declare_lint_rule!` macro if they are work-in-progress to indicate missing features
Applied to files:
crates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/*_analyze/**/src/lint/**/*.rs : Use the `Semantic<T>` query type to access semantic information about bindings, references, and scope within a rule
Applied to files:
crates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs
📚 Learning: 2025-12-31T15:35:32.899Z
Learnt from: dyc3
Repo: biomejs/biome PR: 8639
File: crates/biome_js_analyze/src/lint/nursery/no_excessive_lines_per_file.rs:101-108
Timestamp: 2025-12-31T15:35:32.899Z
Learning: In Rust lint rules under the nursery category, the issue_number field in declare_lint_rule! is optional and should not be added unless there is a compelling reason. In code reviews, verify that no unnecessary issue_number is included in nursery lint declarations. Only add issue_number if there is an explicit, justified reason (e.g., tracked issue for external observers). This guidance broadly applies to all nursery lint rule files, not just the single file.
Applied to files:
crates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/tests/specs/**/* : Create test files with `invalid` and `valid` prefixes to represent code that should and should not trigger the rule
Applied to files:
crates/biome_js_analyze/tests/specs/nursery/useUnicodeRegex/invalid.jscrates/biome_js_analyze/tests/specs/nursery/useUnicodeRegex/valid.js
📚 Learning: 2026-01-02T14:58:16.536Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2026-01-02T14:58:16.536Z
Learning: Applies to crates/biome_analyze/**/tests/specs/**/*.jsonc : Use `.jsonc` format for test files containing multiple code snippets, where each snippet is a string in an array
Applied to files:
crates/biome_js_analyze/tests/specs/nursery/useUnicodeRegex/invalid.jscrates/biome_js_analyze/tests/specs/nursery/useUnicodeRegex/valid.js
📚 Learning: 2025-12-04T13:29:49.287Z
Learnt from: dyc3
Repo: biomejs/biome PR: 8291
File: crates/biome_html_formatter/tests/specs/prettier/vue/html-vue/elastic-header.html:10-10
Timestamp: 2025-12-04T13:29:49.287Z
Learning: Files under `crates/biome_html_formatter/tests/specs/prettier` are test fixtures synced from Prettier and should not receive detailed code quality reviews (e.g., HTTP vs HTTPS, formatting suggestions, etc.). These files are test data meant to validate formatter behavior and should be preserved as-is.
Applied to files:
crates/biome_js_analyze/tests/specs/nursery/useUnicodeRegex/invalid.js
🧬 Code graph analysis (1)
crates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs (1)
crates/biome_js_syntax/src/expr_ext.rs (2)
global_identifier(1914-1934)callee(33-38)
🔇 Additional comments (11)
.changeset/use-unicode-regex-rule.md (1)
1-17: LGTM!The changeset nicely demonstrates both invalid and valid cases as per the contribution guidelines. Clear and concise.
crates/biome_js_analyze/tests/specs/nursery/useUnicodeRegex/invalid.js (1)
1-52: LGTM!Comprehensive test coverage for invalid cases. Nice inclusion of edge cases like trailing commas, parenthesised patterns, and the
globalThis/windowvariants.crates/biome_js_analyze/tests/specs/nursery/useUnicodeRegex/valid.js (1)
1-74: LGTM!Solid coverage of valid scenarios. The dynamic flags and shadowed
RegExpcases are important edge cases to include.crates/biome_rule_options/src/use_unicode_regex.rs (1)
1-6: LGTM!All required derive macros and serde attributes are present as per the coding guidelines.
crates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs (7)
15-72: LGTM!Rule declaration follows all conventions:
version: "next", proper ESLint source attribution with.same(), and comprehensive rustdoc examples.
74-81: LGTM!Good use of
declare_node_union!to avoid redundant traversal passes. The state enum cleanly captures the information needed for the auto-fix.
89-116: LGTM!Clean dispatch logic and informative diagnostic message.
199-208: LGTM!Simple and correct logic for checking regex literal flags.
210-270: LGTM!Good handling of edge cases: spread arguments, dynamic flags, and the no-flags scenario are all correctly addressed.
272-280: LGTM!Correctly leverages
global_identifierto detect the globalRegExpobject whilst respecting shadowed bindings.
282-295: LGTM!Clean extraction of callee and arguments for both
newand call expressions.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| let new_token = JsSyntaxToken::new_detached( | ||
| JsSyntaxKind::JS_STRING_LITERAL, | ||
| &new_flags, | ||
| [], | ||
| [], | ||
| ); | ||
| mutation.replace_token(token, new_token); |
There was a problem hiding this comment.
Trivia is lost when replacing the flags token.
The new token is created with empty trivia arrays, which will discard any leading/trailing comments or whitespace from the original flags argument. Compare this to the literal case (lines 132-141) which preserves trivia.
Suggested fix to preserve trivia
+ let leading: Vec<_> = token.leading_trivia().pieces()
+ .map(|t| TriviaPiece::new(t.kind(), t.text_len()))
+ .collect();
+ let trailing: Vec<_> = token.trailing_trivia().pieces()
+ .map(|t| TriviaPiece::new(t.kind(), t.text_len()))
+ .collect();
+
+ let mut text = String::new();
+ for t in token.leading_trivia().pieces() {
+ text.push_str(t.text());
+ }
+ text.push_str(&new_flags);
+ for t in token.trailing_trivia().pieces() {
+ text.push_str(t.text());
+ }
+
let new_token = JsSyntaxToken::new_detached(
JsSyntaxKind::JS_STRING_LITERAL,
- &new_flags,
- [],
- [],
+ &text,
+ leading,
+ trailing,
);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let new_token = JsSyntaxToken::new_detached( | |
| JsSyntaxKind::JS_STRING_LITERAL, | |
| &new_flags, | |
| [], | |
| [], | |
| ); | |
| mutation.replace_token(token, new_token); | |
| let new_token = JsSyntaxToken::new_detached( | |
| JsSyntaxKind::JS_STRING_LITERAL, | |
| &new_flags, | |
| token.leading_trivia().pieces() | |
| .map(|t| TriviaPiece::new(t.kind(), t.text_len())) | |
| .collect::<Vec<_>>(), | |
| token.trailing_trivia().pieces() | |
| .map(|t| TriviaPiece::new(t.kind(), t.text_len())) | |
| .collect::<Vec<_>>(), | |
| ); | |
| mutation.replace_token(token, new_token); |
🤖 Prompt for AI Agents
In `@crates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs` around lines
178 - 184, Replacing the flags token with JsSyntaxToken::new_detached(..., [],
[],) drops the original token's leading/trailing trivia (comments/whitespace);
when creating the new token for JsSyntaxKind::JS_STRING_LITERAL with new_flags,
capture and pass the original token's trivia into new_detached (e.g., use the
token's leading and trailing trivia accessors) and then call
mutation.replace_token(token, new_token) so comments/whitespace are preserved.
Summary
Implement
useUnicodeRegexnursery rule that enforces the use ofuorvflag for regular expressions. Equivalent to ESLint'srequire-unicode-regexp.The rule detects:
u/vflag:/foo/,/bar/giRegExpconstructor calls:new RegExp("foo"),RegExp("foo", "gi")globalThis.RegExpandwindow.RegExpvariantsProvides auto-fix to add
uflag when possible.Closes #8739
AI Disclosure
This PR was developed with assistance from Claude Code.
Test Plan
valid.jsandinvalid.jstest specscargo test -p biome_js_analyze -- specs::nursery::use_unicode_regexDocs
Documentation is included in the rule's rustdoc comments.