Skip to content

feat(lint/js): add noRestrictedProperties#9806

Merged
dyc3 merged 2 commits into
mainfrom
dyc3/noRestrictedProperties
Jul 23, 2026
Merged

feat(lint/js): add noRestrictedProperties#9806
dyc3 merged 2 commits into
mainfrom
dyc3/noRestrictedProperties

Conversation

@dyc3

@dyc3 dyc3 commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR adds noRestrictedProperties which is a port of https://eslint.org/docs/latest/rules/no-restricted-properties

The main reason to add this rule is that it will be a faster alternative than users writing grit plugins for similar use cases.

generated by gpt 5.4, heavily steered to get it to stop allocating strings

Test Plan

snapshots

Docs

@changeset-bot

changeset-bot Bot commented Apr 5, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: bf82af3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 13 packages
Name Type
@biomejs/biome Patch
@biomejs/cli-win32-x64 Patch
@biomejs/cli-win32-arm64 Patch
@biomejs/cli-darwin-x64 Patch
@biomejs/cli-darwin-arm64 Patch
@biomejs/cli-linux-x64 Patch
@biomejs/cli-linux-arm64 Patch
@biomejs/cli-linux-x64-musl Patch
@biomejs/cli-linux-arm64-musl Patch
@biomejs/wasm-web Patch
@biomejs/wasm-bundler Patch
@biomejs/wasm-nodejs Patch
@biomejs/backend-jsonrpc Patch

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

@github-actions github-actions Bot added A-CLI Area: CLI A-Project Area: project A-Linter Area: linter L-JavaScript Language: JavaScript and super languages A-Diagnostic Area: diagnostocis labels Apr 5, 2026
@codspeed-hq

codspeed-hq Bot commented Apr 5, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 3.74%

⚡ 1 improved benchmark
❌ 34 regressed benchmarks
✅ 235 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
json_formatter[canada_639262044961882324.json] 645.4 ms 686.8 ms -6.03%
pure_9395922602181450299.css[uncached] 4.4 ms 4.6 ms -5.29%
json_formatter[db_17847247775464589309.json] 41.6 ms 43.8 ms -5.02%
graphql_formatter[schema_8546403410957788002.graphql] 2.4 ms 2.5 ms -4.96%
json_formatter[package-lock_11240515041603712709.json] 16.2 ms 17 ms -4.86%
json_formatter[big5-added_15586211152145260264.json] 1.2 ms 1.3 ms -4.77%
js_formatter[jquery.min_16034160674129647344.js] 110.3 ms 115.6 ms -4.56%
json_formatter[eucjp_1600564308684076393.json] 2 ms 2.1 ms -4.5%
js_formatter[pixi.min_8151088792683739606.js] 452.9 ms 473.7 ms -4.39%
js_formatter[react.production.min_3378072959512366797.js] 6.7 ms 7 ms -4.32%
js_formatter[math_5920422916221598348.js] 818.9 ms 855.6 ms -4.29%
js_formatter[vue.global.prod_4065256639735990520.js] 171.2 ms 178.8 ms -4.29%
js_formatter[tex-chtml-full_561698452596513081.js] 1 s 1.1 s -4.24%
graphql_formatter[schema_17790310256719731354.graphql] 23.7 ms 24.7 ms -4.17%
js_formatter[three.min_17199329737537001178.js] 552 ms 575.1 ms -4.01%
js_formatter[d3.min_16009850199655599998.js] 420.5 ms 437.9 ms -3.99%
css_formatter[semantic_4685287698740288120.css] 427.9 ms 445.4 ms -3.93%
js_formatter[router_17129688031671448157.ts] 6.1 ms 6.4 ms -3.85%
js_formatter[dojo_11880045762646467684.js] 26.3 ms 27.3 ms -3.84%
js_formatter[compiler_3469143416596620219.js] 510.1 ms 530.2 ms -3.81%
... ... ... ... ...

ℹ️ Only the first 20 benchmarks are displayed. Go to the app to view all benchmarks.

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing dyc3/noRestrictedProperties (bf82af3) with main (89c27c6)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (ede869c) during the generation of this report, so 89c27c6 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@dyc3
dyc3 force-pushed the dyc3/noRestrictedProperties branch from ccb0e3c to 00f25c4 Compare April 5, 2026 16:18
@dyc3
dyc3 marked this pull request as ready for review April 5, 2026 16:27
@dyc3
dyc3 requested review from a team April 5, 2026 16:28
@coderabbitai

coderabbitai Bot commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds ESLint no-restricted-properties support to biome migrate eslint. The migrator deserialises rule options, converts restricted-property entries, preserves severity and options, and writes Biome’s nursery no_js_restricted_properties configuration. A CLI regression test covers object/property restrictions, allowed properties, and allowed objects. A patch changeset documents the new rule.

Possibly related PRs

  • biomejs/biome#9836: Adds fixture-based infrastructure for custom ESLint rule option migrators in the same migration pipeline.

Suggested labels: A-Tooling

Suggested reviewers: ematipico

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: adding the noRestrictedProperties rule.
Description check ✅ Passed The description is directly related and explains the rule port plus motivation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dyc3/noRestrictedProperties

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

@dyc3
dyc3 force-pushed the dyc3/noRestrictedProperties branch from 00f25c4 to 2d32061 Compare April 6, 2026 13:52

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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

265-277: Minor: Redundant omit_parentheses() call.

Line 270 calls omit_parentheses() on the object, but identifier_object_name (line 416) calls it again internally. The first call is redundant since identifier_object_name handles it.

Not blocking – the duplication is harmless and keeps identifier_object_name self-contained for other call sites (lines 382, 397) that don't pre-strip parentheses.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/biome_js_analyze/src/lint/nursery/no_restricted_properties.rs` around
lines 265 - 277, The call to omit_parentheses() in inspect_member_expression is
redundant because identifier_object_name already calls omit_parentheses
internally; remove the extra omit_parentheses() invocation so
inspect_member_expression passes the raw object (the variable named object) into
identifier_object_name(node.object().ok()?) and keep matching via
match_restriction with identifier_object_name, property_name.text(), and
property_name.range() unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/biome_js_analyze/src/lint/nursery/no_restricted_properties.rs`:
- Around line 265-277: The call to omit_parentheses() in
inspect_member_expression is redundant because identifier_object_name already
calls omit_parentheses internally; remove the extra omit_parentheses()
invocation so inspect_member_expression passes the raw object (the variable
named object) into identifier_object_name(node.object().ok()?) and keep matching
via match_restriction with identifier_object_name, property_name.text(), and
property_name.range() unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 93fccb9e-ea59-420f-aa1c-1840a0abe443

📥 Commits

Reviewing files that changed from the base of the PR and between 00f25c4 and 2d32061.

⛔ Files ignored due to path filters (12)
  • .opencode/package-lock.json is excluded by !**/package-lock.json and included by **
  • Cargo.lock is excluded by !**/*.lock and included by **
  • crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs is excluded by !**/migrate/eslint_any_rule_to_biome.rs and included by **
  • crates/biome_cli/tests/snapshots/main_commands_migrate_eslint/migrate_no_restricted_properties_with_options.snap is excluded by !**/*.snap and included by **
  • crates/biome_configuration/src/analyzer/linter/rules.rs is excluded by !**/rules.rs and included by **
  • crates/biome_configuration/src/generated/linter_options_check.rs is excluded by !**/generated/**, !**/generated/** and included by **
  • crates/biome_diagnostics_categories/src/categories.rs is excluded by !**/categories.rs and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noRestrictedProperties/invalid.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noRestrictedProperties/invalidConfig.js.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/nursery/noRestrictedProperties/valid.js.snap is excluded by !**/*.snap and included by **
  • packages/@biomejs/backend-jsonrpc/src/workspace.ts is excluded by !**/backend-jsonrpc/src/workspace.ts and included by **
  • packages/@biomejs/biome/configuration_schema.json is excluded by !**/configuration_schema.json and included by **
📒 Files selected for processing (14)
  • .changeset/thick-coins-hide.md
  • crates/biome_cli/src/execute/migrate/eslint_eslint.rs
  • crates/biome_cli/src/execute/migrate/eslint_to_biome.rs
  • crates/biome_cli/tests/commands/migrate_eslint.rs
  • crates/biome_js_analyze/src/lint/nursery/no_restricted_properties.rs
  • crates/biome_js_analyze/tests/specs/nursery/noRestrictedProperties/invalid.js
  • crates/biome_js_analyze/tests/specs/nursery/noRestrictedProperties/invalid.options.json
  • crates/biome_js_analyze/tests/specs/nursery/noRestrictedProperties/invalidConfig.js
  • crates/biome_js_analyze/tests/specs/nursery/noRestrictedProperties/invalidConfig.options.json
  • crates/biome_js_analyze/tests/specs/nursery/noRestrictedProperties/valid.js
  • crates/biome_js_analyze/tests/specs/nursery/noRestrictedProperties/valid.options.json
  • crates/biome_rule_options/Cargo.toml
  • crates/biome_rule_options/src/lib.rs
  • crates/biome_rule_options/src/no_restricted_properties.rs
✅ Files skipped from review due to trivial changes (9)
  • crates/biome_rule_options/src/lib.rs
  • crates/biome_rule_options/Cargo.toml
  • .changeset/thick-coins-hide.md
  • crates/biome_js_analyze/tests/specs/nursery/noRestrictedProperties/valid.js
  • crates/biome_js_analyze/tests/specs/nursery/noRestrictedProperties/invalidConfig.js
  • crates/biome_js_analyze/tests/specs/nursery/noRestrictedProperties/invalid.options.json
  • crates/biome_js_analyze/tests/specs/nursery/noRestrictedProperties/invalidConfig.options.json
  • crates/biome_js_analyze/tests/specs/nursery/noRestrictedProperties/valid.options.json
  • crates/biome_js_analyze/tests/specs/nursery/noRestrictedProperties/invalid.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/biome_cli/src/execute/migrate/eslint_eslint.rs

@ematipico ematipico left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Code looks fine, but docs need some rework

Comment thread crates/biome_js_analyze/src/lint/nursery/no_restricted_properties.rs Outdated
@dyc3
dyc3 force-pushed the dyc3/noRestrictedProperties branch from 2d32061 to 67e873c Compare April 17, 2026 20:28

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
crates/biome_cli/tests/commands/migrate_eslint.rs (1)

407-458: Nice test — consider adding the severity-only sibling case.

This covers populated entries well; a tiny "error"-only case would also lock down the entries: None branch.

Suggested companion test
+#[test]
+fn migrate_no_restricted_properties_no_options() {
+    let biomejson = r#"{}"#;
+    let eslintrc = r#"{ "rules": { "no-restricted-properties": "error" } }"#;
+
+    let fs = MemoryFileSystem::default();
+    fs.insert(Utf8Path::new("biome.json").into(), biomejson.as_bytes());
+    fs.insert(Utf8Path::new(".eslintrc.json").into(), eslintrc.as_bytes());
+
+    let mut console = BufferConsole::default();
+    let (fs, result) = run_cli(
+        fs,
+        &mut console,
+        Args::from(
+            ["migrate", "eslint", "--include-nursery", "--write"].as_slice(),
+        ),
+    );
+
+    assert!(result.is_ok(), "run_cli returned {result:?}");
+    assert_cli_snapshot(SnapshotPayload::new(
+        module_path!(),
+        "migrate_no_restricted_properties_no_options",
+        fs,
+        console,
+        result,
+    ));
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/biome_cli/tests/commands/migrate_eslint.rs` around lines 407 - 458,
Add a companion test to cover the severity-only branch: create a new test (e.g.,
migrate_no_restricted_properties_severity_only) that supplies a .eslintrc.json
where "no-restricted-properties" is just ["error"] (no entries object/array),
mirror the same MemoryFileSystem, BufferConsole and run_cli invocation used in
migrate_no_restricted_properties_with_options (Args::from with
"migrate","eslint","--include-inspired","--include-nursery","--write"), assert
run_cli is Ok and call assert_cli_snapshot with the new test name to lock down
the entries: None branch.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/biome_cli/tests/commands/migrate_eslint.rs`:
- Around line 407-458: Add a companion test to cover the severity-only branch:
create a new test (e.g., migrate_no_restricted_properties_severity_only) that
supplies a .eslintrc.json where "no-restricted-properties" is just ["error"] (no
entries object/array), mirror the same MemoryFileSystem, BufferConsole and
run_cli invocation used in migrate_no_restricted_properties_with_options
(Args::from with
"migrate","eslint","--include-inspired","--include-nursery","--write"), assert
run_cli is Ok and call assert_cli_snapshot with the new test name to lock down
the entries: None branch.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 54eff383-6850-4d7d-8e9b-e3adae95b249

📥 Commits

Reviewing files that changed from the base of the PR and between 2d32061 and 67e873c.

⛔ Files ignored due to path filters (5)
  • Cargo.lock is excluded by !**/*.lock and included by **
  • crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs is excluded by !**/migrate/eslint_any_rule_to_biome.rs and included by **
  • crates/biome_cli/tests/snapshots/main_commands_migrate_eslint/migrate_no_restricted_properties_with_options.snap is excluded by !**/*.snap and included by **
  • crates/biome_configuration/src/analyzer/linter/rules.rs is excluded by !**/rules.rs and included by **
  • crates/biome_configuration/src/generated/linter_options_check.rs is excluded by !**/generated/**, !**/generated/** and included by **
📒 Files selected for processing (4)
  • .changeset/thick-coins-hide.md
  • crates/biome_cli/src/execute/migrate/eslint_eslint.rs
  • crates/biome_cli/src/execute/migrate/eslint_to_biome.rs
  • crates/biome_cli/tests/commands/migrate_eslint.rs
✅ Files skipped from review due to trivial changes (1)
  • .changeset/thick-coins-hide.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/biome_cli/src/execute/migrate/eslint_eslint.rs

@dyc3
dyc3 force-pushed the dyc3/noRestrictedProperties branch from 67e873c to 8f36d38 Compare April 17, 2026 20:37
@dyc3

dyc3 commented Apr 17, 2026

Copy link
Copy Markdown
Contributor Author

Ok, I've rewritten the options docs by hand. I know that we usually put examples before options, but for this rule specifically: should we have the options first? I think it could make it flow better. We introduce the user to the options and how they work, then provide examples to demonstrate.

@dyc3
dyc3 requested a review from ematipico April 17, 2026 20:52

@ematipico ematipico left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I left some suggestions for the docs. As for rule, it's a rule specially tailored for JavaScript, and that's confirmed by the way the options are treated. Remember that options are shared across languages.

When rules are designed for a language or domain, they should carry their language in their name. For example useGraphqlNamingConvention. This rule should be named noJsRestrictedProperties. I don't see this rule being ported to other languages, because of the way identifiers are treated.

Comment thread crates/biome_js_analyze/src/lint/nursery/no_restricted_properties.rs Outdated
Comment thread crates/biome_js_analyze/src/lint/nursery/no_restricted_properties.rs Outdated
Comment thread crates/biome_js_analyze/src/lint/nursery/no_restricted_properties.rs Outdated
Comment on lines +107 to +111
/// An array of restricted object/property combinations. Depending on the provided options, each entry can:
/// - Restrict a specific property on a specific object.
/// - Restrict all properties on a specific object except for an allowlist of properties.
/// - Restrict a specific property everywhere except for an allowlist of objects.
/// - Provide a custom message to include in the diagnostic when the restriction is violated.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
/// An array of restricted object/property combinations. Depending on the provided options, each entry can:
/// - Restrict a specific property on a specific object.
/// - Restrict all properties on a specific object except for an allowlist of properties.
/// - Restrict a specific property everywhere except for an allowlist of objects.
/// - Provide a custom message to include in the diagnostic when the restriction is violated.
/// An array of restricted object/property combinations.

I removed the list because we're repeating the examples and the description of the properties below.

Comment thread crates/biome_js_analyze/src/lint/nursery/no_restricted_properties.rs Outdated
Comment thread crates/biome_js_analyze/src/lint/nursery/no_restricted_properties.rs Outdated
Comment on lines +121 to +127
/// ### `entries[].allowObjects`
///
/// When restricting a property, an optional allowlist of objects that are exempt from the restriction. Only applicable when `property` is provided and `object` is not provided.
///
/// ### `entries[].allowProperties`
///
/// When restricting an object, an optional allowlist of properties that are exempt from the restriction. Only applicable when `object` is provided and `property` is not provided.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Here's a legitimate question that the docs should explain.

What if the configuration provides both? From what I read, the allow lists work only in certain conditions. If both property and object are provided, what happens?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That's exactly what I was trying to address with the bullet points up here that you want removed: #9806 (comment)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh, I didn't understand that from the bullet list :(

Comment thread crates/biome_rule_options/src/no_restricted_properties.rs Outdated
Comment thread crates/biome_rule_options/src/no_restricted_properties.rs Outdated
@ematipico

Copy link
Copy Markdown
Member

Friendly bump @dyc3

@dyc3
dyc3 force-pushed the dyc3/noRestrictedProperties branch from 8f36d38 to da0e956 Compare July 23, 2026 15:14
@dyc3
dyc3 requested a review from ematipico July 23, 2026 15:16
@dyc3
dyc3 merged commit 781d68d into main Jul 23, 2026
40 of 41 checks passed
@dyc3
dyc3 deleted the dyc3/noRestrictedProperties branch July 23, 2026 18:17
@github-actions github-actions Bot mentioned this pull request Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-CLI Area: CLI A-Diagnostic Area: diagnostocis A-Linter Area: linter A-Project Area: project L-JavaScript Language: JavaScript and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants