Skip to content

perf: reduced queries in rules#10258

Merged
ematipico merged 5 commits into
mainfrom
perf/reduce-queries-in-rules
May 7, 2026
Merged

perf: reduced queries in rules#10258
ematipico merged 5 commits into
mainfrom
perf/reduce-queries-in-rules

Conversation

@ematipico

Copy link
Copy Markdown
Member

Summary

This PR narrows down the query of some rules. I realised this when testing Biome against big repositories, and realised that some rules were executed a lot, via --profile-rules

This PR reduces the number of nodes queried because of what they need to actually inspect.

I wrote the foundation of the change, and then asked a coding agent to update the rest of the rules.

Test Plan

Green CI

Docs

@changeset-bot

changeset-bot Bot commented May 5, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2e8108a

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

@ematipico ematipico force-pushed the perf/reduce-queries-in-rules branch from 3210dcc to 5ac164a Compare May 5, 2026 14:49
@github-actions github-actions Bot added A-Linter Area: linter A-Parser Area: parser L-JavaScript Language: JavaScript and super languages labels May 5, 2026
@coderabbitai

coderabbitai Bot commented May 5, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This PR adds a new node union AnyPossibleGlobalIdentifier, implements AnyJsExpression::as_any_global_identifier_expression(), and updates global_identifier to accept &AnyPossibleGlobalIdentifier. Many lint rules were refactored to convert expressions via the new accessor before calling global_identifier, tightening identifier matching and in some cases narrowing rule query types. The no_extra_boolean_cast rule adds AnyBooleanCastLike and updates its query and fix application. Other changes propagate scope/owner-scope metadata into the semantic model to support the new analyses.

Possibly related PRs

  • biomejs/biome#10104: Direct overlap — introduces AnyPossibleGlobalIdentifier / as_any_global_identifier_expression and narrows lint queries in the same files/logic.
  • biomejs/biome#10088: Touches the same lint-rule implementations (several crates/biome_js_analyze lint files) that this PR refactors for identifier extraction.
  • biomejs/biome#9701: Related to no_useless_type_conversion and identifier-resolution patterns that this PR changes to use as_any_global_identifier_expression().

Suggested labels

L-CSS

Suggested reviewers

  • Conaclos
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: reducing query scope in linting rules for performance.
Description check ✅ Passed The description adequately explains the motivation (profiling revealed overly broad queries), approach (author implemented foundation + agent-assisted updates), and test plan.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/reduce-queries-in-rules

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

@ematipico ematipico requested review from a team May 5, 2026 14:53
@github-actions

github-actions Bot commented May 5, 2026

Copy link
Copy Markdown
Contributor

Parser conformance results on

js/262

Test result main count This PR count Difference
Total 53193 53193 0
Passed 51975 51975 0
Failed 1176 1176 0
Panics 42 42 0
Coverage 97.71% 97.71% 0.00%

jsx/babel

Test result main count This PR count Difference
Total 38 38 0
Passed 37 37 0
Failed 1 1 0
Panics 0 0 0
Coverage 97.37% 97.37% 0.00%

markdown/commonmark

Test result main count This PR count Difference
Total 652 652 0
Passed 652 652 0
Failed 0 0 0
Panics 0 0 0
Coverage 100.00% 100.00% 0.00%

symbols/microsoft

Test result main count This PR count Difference
Total 5467 5467 0
Passed 1915 1915 0
Failed 3552 3552 0
Panics 0 0 0
Coverage 35.03% 35.03% 0.00%

ts/babel

Test result main count This PR count Difference
Total 658 658 0
Passed 574 574 0
Failed 84 84 0
Panics 0 0 0
Coverage 87.23% 87.23% 0.00%

ts/microsoft

Test result main count This PR count Difference
Total 18876 18876 0
Passed 13010 13010 0
Failed 5865 5865 0
Panics 1 1 0
Coverage 68.92% 68.92% 0.00%

@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.

Actionable comments posted: 5

🧹 Nitpick comments (2)
crates/biome_js_analyze/src/lint/correctness/use_is_nan.rs (1)

316-320: 💤 Low value

Redundant omit_parentheses() call.

member_object is already the result of omit_parentheses() on line 315, so calling it again on line 318 is unnecessary.

🧹 Proposed simplification
-            let (reference, name) = global_identifier(
-                &member_object
-                    .omit_parentheses()
-                    .as_any_global_identifier_expression()?,
-            )?;
+            let (reference, name) =
+                global_identifier(&member_object.as_any_global_identifier_expression()?)?;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/biome_js_analyze/src/lint/correctness/use_is_nan.rs` around lines 316
- 320, The call to omit_parentheses() is duplicated: member_object was already
obtained via omit_parentheses() earlier, so remove the redundant second call
when passing to global_identifier; change the argument to global_identifier to
use member_object.as_any_global_identifier_expression()? directly (i.e., drop
the extra member_object.omit_parentheses()), leaving the rest of the invocation
(global_identifier(...)? and the let (reference, name) = ...) unchanged.
crates/biome_js_analyze/src/lint/nursery/no_implied_eval.rs (1)

223-227: 💤 Low value

Remove unnecessary .clone() on line 224.

expression is already a reference, and as_any_global_identifier_expression() takes &self, so the clone is redundant. Rust's auto-deref handles this without needing an owned copy.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/biome_js_analyze/src/lint/nursery/no_implied_eval.rs` around lines 223
- 227, Remove the unnecessary .clone() call on expression in the pattern
matching line: expression.clone().as_any_global_identifier_expression() should
be called directly on expression because as_any_global_identifier_expression()
takes &self and expression is already a reference; update the let binding to
call expression.as_any_global_identifier_expression().and_then(|e|
global_identifier(&e)) (keeping the surrounding let Some((reference, name)) =
... else { } intact) so no owned clone is created.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/biome_js_analyze/src/lint/complexity/no_extra_boolean_cast.rs`:
- Around line 96-110: The narrowed union AnyBooleanCastLike removed
JsNewExpression but run() still handles JsNewExpression (see run() and
JsNewExpression::cast_ref), so restore JsNewExpression to the union and ensure
as_any_js_expression maps it to AnyJsExpression::JsNewExpression; update the
declare_node_union to include JsNewExpression and add the matching arm in
as_any_js_expression so NoExtraBooleanCast::run() can still receive and process
new Boolean(...) expressions.

In `@crates/biome_js_analyze/src/lint/style/no_process_env.rs`:
- Around line 65-66: The check should normalize parenthesised objects before
extracting the global identifier: call omit_parentheses() on the object and then
pass the normalized object into as_any_global_identifier_expression() and
global_identifier(); i.e., replace the direct use of object in the
global_identifier(&object.as_any_global_identifier_expression()?) call by first
calling object.omit_parentheses() (then use that normalized object's
as_any_global_identifier_expression() with global_identifier()) so cases like
(process).env are caught.

In `@crates/biome_js_analyze/src/lint/style/use_number_namespace.rs`:
- Around line 213-223: Special-case computed member access with property string
"Infinity" inside the AnyJsMemberExpression::JsComputedMemberExpression arm: if
the property is a string literal "Infinity" then do NOT prepend Number as a
static member; instead replace the whole expression with the appropriate numeric
member (Number.POSITIVE_INFINITY or Number.NEGATIVE_INFINITY) and preserve the
unary +/- parent replacement used by the other arms (reuse the same parent-check
and replacement logic). Concretely, detect the property token value "Infinity",
choose make::js_static_member_expression(object? no — replace node entirely with
make::js_static_member_expression(make::js_name(make::ident("Number")),
make::token(T![.]), make::js_name(make::ident("POSITIVE_INFINITY")) ) or
NEGATIVE when a unary - parent is present, and apply the same unary parent
transformation used by the other branches so runtime semantics are unchanged.

In `@crates/biome_js_analyze/src/lint/suspicious/no_alert.rs`:
- Around line 135-136: The code is missing omit_parentheses() when locating
global identifiers in member-object paths, so parenthesised globals like
(window).alert or (globalThis)["alert"] are not recognized; update both call
sites that use object.as_any_global_identifier_expression()? and similar at the
other occurrence to first call object.omit_parentheses() (and then
as_any_global_identifier_expression()?) so the global_identifier(...) receives
the unparenthesised expression; adjust the binding that currently does let
(reference, object_name) =
global_identifier(&object.as_any_global_identifier_expression()?)? to use
global_identifier(&object.omit_parentheses().as_any_global_identifier_expression()?)?
(and the analogous change for the second occurrence) ensuring proper error
handling remains.

In `@crates/biome_js_analyze/src/lint/suspicious/use_iterable_callback_return.rs`:
- Around line 175-180: The code calling global_identifier currently uses
member_expression.object().ok()?.as_any_global_identifier_expression()? without
normalizing parentheses; update the lookup to normalize the object first by
invoking omit_parentheses() (i.e., use
member_expression.object().ok()?.omit_parentheses().as_any_global_identifier_expression()?)
before passing to global_identifier so cases like (Array).from(...) are detected
consistent with other rules.

---

Nitpick comments:
In `@crates/biome_js_analyze/src/lint/correctness/use_is_nan.rs`:
- Around line 316-320: The call to omit_parentheses() is duplicated:
member_object was already obtained via omit_parentheses() earlier, so remove the
redundant second call when passing to global_identifier; change the argument to
global_identifier to use member_object.as_any_global_identifier_expression()?
directly (i.e., drop the extra member_object.omit_parentheses()), leaving the
rest of the invocation (global_identifier(...)? and the let (reference, name) =
...) unchanged.

In `@crates/biome_js_analyze/src/lint/nursery/no_implied_eval.rs`:
- Around line 223-227: Remove the unnecessary .clone() call on expression in the
pattern matching line: expression.clone().as_any_global_identifier_expression()
should be called directly on expression because
as_any_global_identifier_expression() takes &self and expression is already a
reference; update the let binding to call
expression.as_any_global_identifier_expression().and_then(|e|
global_identifier(&e)) (keeping the surrounding let Some((reference, name)) =
... else { } intact) so no owned clone is created.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4c776bc1-2fbf-45ee-be08-a359f4ed43f6

📥 Commits

Reviewing files that changed from the base of the PR and between 0ae5840 and 5ac164a.

📒 Files selected for processing (36)
  • .changeset/sixty-hairs-rush.md
  • crates/biome_js_analyze/src/lint/complexity/no_extra_boolean_cast.rs
  • crates/biome_js_analyze/src/lint/complexity/use_numeric_literals.rs
  • crates/biome_js_analyze/src/lint/complexity/use_regex_literals.rs
  • crates/biome_js_analyze/src/lint/correctness/no_constant_math_min_max_clamp.rs
  • crates/biome_js_analyze/src/lint/correctness/no_global_object_calls.rs
  • crates/biome_js_analyze/src/lint/correctness/no_invalid_builtin_instantiation.rs
  • crates/biome_js_analyze/src/lint/correctness/no_process_global.rs
  • crates/biome_js_analyze/src/lint/correctness/no_qwik_use_visible_task.rs
  • crates/biome_js_analyze/src/lint/correctness/use_is_nan.rs
  • crates/biome_js_analyze/src/lint/correctness/use_parse_int_radix.rs
  • crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs
  • crates/biome_js_analyze/src/lint/nursery/no_implied_eval.rs
  • crates/biome_js_analyze/src/lint/nursery/no_undeclared_env_vars.rs
  • crates/biome_js_analyze/src/lint/nursery/no_useless_type_conversion.rs
  • crates/biome_js_analyze/src/lint/nursery/use_named_capture_group.rs
  • crates/biome_js_analyze/src/lint/nursery/use_unicode_regex.rs
  • crates/biome_js_analyze/src/lint/security/no_global_eval.rs
  • crates/biome_js_analyze/src/lint/style/no_common_js.rs
  • crates/biome_js_analyze/src/lint/style/no_process_env.rs
  • crates/biome_js_analyze/src/lint/style/use_array_literals.rs
  • crates/biome_js_analyze/src/lint/style/use_consistent_builtin_instantiation.rs
  • crates/biome_js_analyze/src/lint/style/use_exponentiation_operator.rs
  • crates/biome_js_analyze/src/lint/style/use_number_namespace.rs
  • crates/biome_js_analyze/src/lint/style/use_object_spread.rs
  • crates/biome_js_analyze/src/lint/style/use_symbol_description.rs
  • crates/biome_js_analyze/src/lint/suspicious/no_alert.rs
  • crates/biome_js_analyze/src/lint/suspicious/no_console.rs
  • crates/biome_js_analyze/src/lint/suspicious/no_document_cookie.rs
  • crates/biome_js_analyze/src/lint/suspicious/no_global_is_finite.rs
  • crates/biome_js_analyze/src/lint/suspicious/no_global_is_nan.rs
  • crates/biome_js_analyze/src/lint/suspicious/use_error_message.rs
  • crates/biome_js_analyze/src/lint/suspicious/use_is_array.rs
  • crates/biome_js_analyze/src/lint/suspicious/use_iterable_callback_return.rs
  • crates/biome_js_analyze/src/lint/suspicious/use_static_response_methods.rs
  • crates/biome_js_syntax/src/expr_ext.rs

Comment on lines +96 to +110
declare_node_union! {
pub AnyBooleanCastLike = JsUnaryExpression | JsCallExpression
}

impl AnyBooleanCastLike {
pub(crate) fn as_any_js_expression(&self) -> AnyJsExpression {
match self {
Self::JsUnaryExpression(expr) => AnyJsExpression::JsUnaryExpression(expr.clone()),
Self::JsCallExpression(expr) => AnyJsExpression::JsCallExpression(expr.clone()),
}
}
}

impl Rule for NoExtraBooleanCast {
type Query = Ast<AnyJsExpression>;
type Query = Ast<AnyBooleanCastLike>;

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep JsNewExpression in the narrowed query union.

run() still has a JsNewExpression::cast_ref(n.syntax()) path at Lines 154-170, but AnyBooleanCastLike can no longer produce that node. That quietly drops cases like if (new Boolean(foo)) {} from the rule after this perf tweak.

Possible fix
 declare_node_union! {
-    pub AnyBooleanCastLike = JsUnaryExpression | JsCallExpression
+    pub AnyBooleanCastLike = JsUnaryExpression | JsCallExpression | JsNewExpression
 }
 
 impl AnyBooleanCastLike {
     pub(crate) fn as_any_js_expression(&self) -> AnyJsExpression {
         match self {
             Self::JsUnaryExpression(expr) => AnyJsExpression::JsUnaryExpression(expr.clone()),
             Self::JsCallExpression(expr) => AnyJsExpression::JsCallExpression(expr.clone()),
+            Self::JsNewExpression(expr) => AnyJsExpression::JsNewExpression(expr.clone()),
         }
     }
 }
📝 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.

Suggested change
declare_node_union! {
pub AnyBooleanCastLike = JsUnaryExpression | JsCallExpression
}
impl AnyBooleanCastLike {
pub(crate) fn as_any_js_expression(&self) -> AnyJsExpression {
match self {
Self::JsUnaryExpression(expr) => AnyJsExpression::JsUnaryExpression(expr.clone()),
Self::JsCallExpression(expr) => AnyJsExpression::JsCallExpression(expr.clone()),
}
}
}
impl Rule for NoExtraBooleanCast {
type Query = Ast<AnyJsExpression>;
type Query = Ast<AnyBooleanCastLike>;
declare_node_union! {
pub AnyBooleanCastLike = JsUnaryExpression | JsCallExpression | JsNewExpression
}
impl AnyBooleanCastLike {
pub(crate) fn as_any_js_expression(&self) -> AnyJsExpression {
match self {
Self::JsUnaryExpression(expr) => AnyJsExpression::JsUnaryExpression(expr.clone()),
Self::JsCallExpression(expr) => AnyJsExpression::JsCallExpression(expr.clone()),
Self::JsNewExpression(expr) => AnyJsExpression::JsNewExpression(expr.clone()),
}
}
}
impl Rule for NoExtraBooleanCast {
type Query = Ast<AnyBooleanCastLike>;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/biome_js_analyze/src/lint/complexity/no_extra_boolean_cast.rs` around
lines 96 - 110, The narrowed union AnyBooleanCastLike removed JsNewExpression
but run() still handles JsNewExpression (see run() and
JsNewExpression::cast_ref), so restore JsNewExpression to the union and ensure
as_any_js_expression maps it to AnyJsExpression::JsNewExpression; update the
declare_node_union to include JsNewExpression and add the matching arm in
as_any_js_expression so NoExtraBooleanCast::run() can still receive and process
new Boolean(...) expressions.

Comment on lines +65 to +66
let (reference, name) =
global_identifier(&object.as_any_global_identifier_expression()?)?;

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Handle parenthesised process objects too

Line 66 should normalise object with omit_parentheses() first; otherwise (process).env can evade this rule.

Suggested patch
-        let (reference, name) =
-            global_identifier(&object.as_any_global_identifier_expression()?)?;
+        let (reference, name) = global_identifier(
+            &object
+                .omit_parentheses()
+                .as_any_global_identifier_expression()?,
+        )?;
📝 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.

Suggested change
let (reference, name) =
global_identifier(&object.as_any_global_identifier_expression()?)?;
let (reference, name) = global_identifier(
&object
.omit_parentheses()
.as_any_global_identifier_expression()?,
)?;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/biome_js_analyze/src/lint/style/no_process_env.rs` around lines 65 -
66, The check should normalize parenthesised objects before extracting the
global identifier: call omit_parentheses() on the object and then pass the
normalized object into as_any_global_identifier_expression() and
global_identifier(); i.e., replace the direct use of object in the
global_identifier(&object.as_any_global_identifier_expression()?) call by first
calling object.omit_parentheses() (then use that normalized object's
as_any_global_identifier_expression() with global_identifier()) so cases like
(process).env are caught.

Comment on lines +213 to +223
AnyJsMemberExpression::JsComputedMemberExpression(expression) => {
let object = expression.object().ok()?;
(
object.clone(),
make::js_static_member_expression(
object,
make::token(T![.]),
make::js_name(make::ident("Number")).into(),
)
.into(),
expression.operator_token().ok()?,
make::js_name(make::ident(replacement)).into(),
),
)
}
AnyJsExpression::JsComputedMemberExpression(expression) => {
let object = expression.object().ok()?;
(
object.clone(),
make::js_static_member_expression(
object,
make::token(T![.]),
make::js_name(make::ident("Number")).into(),
),
)
}
_ => return None,
),
)
}

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Handle ["Infinity"] before prepending Number.

This arm rewrites window["Infinity"] to window.Number["Infinity"], but that property does not exist — the correct target is Number.POSITIVE_INFINITY / Number.NEGATIVE_INFINITY. It also skips the unary +/- parent replacement handled in the other branches, so the current safe fix can change runtime behaviour.

Possible fix
                 AnyJsMemberExpression::JsComputedMemberExpression(expression) => {
                     let object = expression.object().ok()?;
-                    (
-                        object.clone(),
-                        make::js_static_member_expression(
-                            object,
-                            make::token(T![.]),
-                            make::js_name(make::ident("Number")).into(),
-                        ),
-                    )
+                    if global_ident.text() == "Infinity" {
+                        let replacement = if let Some(parent) = node.parent::<JsUnaryExpression>() {
+                            match parent.operator().ok()? {
+                                JsUnaryOperator::Minus => "NEGATIVE_INFINITY",
+                                JsUnaryOperator::Plus => "POSITIVE_INFINITY",
+                                _ => return None,
+                            }
+                        } else {
+                            "POSITIVE_INFINITY"
+                        };
+
+                        (
+                            node_expr,
+                            make::js_static_member_expression(
+                                make::js_static_member_expression(
+                                    object,
+                                    make::token(T![.]),
+                                    make::js_name(make::ident("Number")).into(),
+                                )
+                                .into(),
+                                make::token(T![.]),
+                                make::js_name(make::ident(replacement)).into(),
+                            ),
+                        )
+                    } else {
+                        (
+                            object.clone(),
+                            make::js_static_member_expression(
+                                object,
+                                make::token(T![.]),
+                                make::js_name(make::ident("Number")).into(),
+                            ),
+                        )
+                    }
                 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/biome_js_analyze/src/lint/style/use_number_namespace.rs` around lines
213 - 223, Special-case computed member access with property string "Infinity"
inside the AnyJsMemberExpression::JsComputedMemberExpression arm: if the
property is a string literal "Infinity" then do NOT prepend Number as a static
member; instead replace the whole expression with the appropriate numeric member
(Number.POSITIVE_INFINITY or Number.NEGATIVE_INFINITY) and preserve the unary
+/- parent replacement used by the other arms (reuse the same parent-check and
replacement logic). Concretely, detect the property token value "Infinity",
choose make::js_static_member_expression(object? no — replace node entirely with
make::js_static_member_expression(make::js_name(make::ident("Number")),
make::token(T![.]), make::js_name(make::ident("POSITIVE_INFINITY")) ) or
NEGATIVE when a unary - parent is present, and apply the same unary parent
transformation used by the other branches so runtime semantics are unchanged.

Comment on lines +135 to +136
let (reference, object_name) =
global_identifier(&object.as_any_global_identifier_expression()?)?;

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Handle parenthesised globals in member-object paths.

Line 135 and Line 155 skip omit_parentheses() before casting, so cases like (window).alert() / (globalThis)["alert"]() can fall through and miss diagnostics.

💡 Suggested patch
 fn check_static_member_expression(
     member_expr: &JsStaticMemberExpression,
     model: &SemanticModel,
 ) -> Option<&'static str> {
-    let object = member_expr.object().ok()?;
+    let object = member_expr.object().ok()?.omit_parentheses();
     let (reference, object_name) =
         global_identifier(&object.as_any_global_identifier_expression()?)?;
     let object_name_text = object_name.text();
@@
 fn check_computed_member_expression(
     computed_member_expr: &JsComputedMemberExpression,
     model: &SemanticModel,
 ) -> Option<&'static str> {
-    let object = computed_member_expr.object().ok()?;
+    let object = computed_member_expr.object().ok()?.omit_parentheses();
     let (reference, object_name) =
         global_identifier(&object.as_any_global_identifier_expression()?)?;
     let object_name_text = object_name.text();

Also applies to: 155-156

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/biome_js_analyze/src/lint/suspicious/no_alert.rs` around lines 135 -
136, The code is missing omit_parentheses() when locating global identifiers in
member-object paths, so parenthesised globals like (window).alert or
(globalThis)["alert"] are not recognized; update both call sites that use
object.as_any_global_identifier_expression()? and similar at the other
occurrence to first call object.omit_parentheses() (and then
as_any_global_identifier_expression()?) so the global_identifier(...) receives
the unparenthesised expression; adjust the binding that currently does let
(reference, object_name) =
global_identifier(&object.as_any_global_identifier_expression()?)? to use
global_identifier(&object.omit_parentheses().as_any_global_identifier_expression()?)?
(and the analogous change for the second occurrence) ensuring proper error
handling remains.

Comment on lines +175 to +180
let (_, name) = global_identifier(
&member_expression
.object()
.ok()?
.as_any_global_identifier_expression()?,
)?;

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Normalise the object before global lookup

On Line 177, this path skips omit_parentheses(), so (Array).from(...) can be missed. Adding it keeps behaviour aligned with the other migrated rules.

Suggested patch
-            let (_, name) = global_identifier(
-                &member_expression
-                    .object()
-                    .ok()?
-                    .as_any_global_identifier_expression()?,
-            )?;
+            let (_, name) = global_identifier(
+                &member_expression
+                    .object()
+                    .ok()?
+                    .omit_parentheses()
+                    .as_any_global_identifier_expression()?,
+            )?;
📝 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.

Suggested change
let (_, name) = global_identifier(
&member_expression
.object()
.ok()?
.as_any_global_identifier_expression()?,
)?;
let (_, name) = global_identifier(
&member_expression
.object()
.ok()?
.omit_parentheses()
.as_any_global_identifier_expression()?,
)?;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/biome_js_analyze/src/lint/suspicious/use_iterable_callback_return.rs`
around lines 175 - 180, The code calling global_identifier currently uses
member_expression.object().ok()?.as_any_global_identifier_expression()? without
normalizing parentheses; update the lookup to normalize the object first by
invoking omit_parentheses() (i.e., use
member_expression.object().ok()?.omit_parentheses().as_any_global_identifier_expression()?)
before passing to global_identifier so cases like (Array).from(...) are detected
consistent with other rules.

@codspeed-hq

codspeed-hq Bot commented May 5, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 87 untouched benchmarks
⏩ 167 skipped benchmarks1


Comparing perf/reduce-queries-in-rules (2e8108a) with main (e0a54cc)2

Open in CodSpeed

Footnotes

  1. 167 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.

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

@Conaclos

Conaclos commented May 5, 2026

Copy link
Copy Markdown
Member

Did you notice perf improvements?

@github-actions github-actions Bot added the L-CSS Language: CSS and super languages label May 5, 2026

@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/correctness/no_invalid_use_before_declaration.rs (1)

306-322: 💤 Low value

Remove the unused AnyJsVariableScope union type declaration. It's no longer referenced anywhere in the codebase after the refactoring to use Scope::is_variable_scope().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@crates/biome_js_analyze/src/lint/correctness/no_invalid_use_before_declaration.rs`
around lines 306 - 322, Remove the unused union type declaration
AnyJsVariableScope: locate the declare_node_union! block that defines
AnyJsVariableScope and delete it; verify that no references remain (the codebase
now uses Scope::is_variable_scope()), then run a build to ensure no unresolved
symbols are introduced and update any imports or re-exports that referenced
AnyJsVariableScope if present.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@crates/biome_js_analyze/src/lint/correctness/no_invalid_use_before_declaration.rs`:
- Around line 306-322: Remove the unused union type declaration
AnyJsVariableScope: locate the declare_node_union! block that defines
AnyJsVariableScope and delete it; verify that no references remain (the codebase
now uses Scope::is_variable_scope()), then run a build to ensure no unresolved
symbols are introduced and update any imports or re-exports that referenced
AnyJsVariableScope if present.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 25ef6fb6-931c-4b56-a2f5-e548386fe39d

📥 Commits

Reviewing files that changed from the base of the PR and between 8baca41 and 80f2bc8.

📒 Files selected for processing (6)
  • crates/biome_css_analyze/src/lint/style/no_descending_specificity.rs
  • crates/biome_js_analyze/src/lint/correctness/no_invalid_use_before_declaration.rs
  • crates/biome_js_semantic/src/events.rs
  • crates/biome_js_semantic/src/semantic_model/binding.rs
  • crates/biome_js_semantic/src/semantic_model/builder.rs
  • crates/biome_js_semantic/src/semantic_model/scope.rs

@ematipico

Copy link
Copy Markdown
Member Author

Did you notice perf improvements?

I need to trigger a preview release first.

@ematipico ematipico force-pushed the perf/reduce-queries-in-rules branch from 80f2bc8 to e8fe3d7 Compare May 5, 2026 17:42
@ematipico

Copy link
Copy Markdown
Member Author

@Conaclos

Generated via AI

Takeaways

  1. The "after" run is ~6% faster on average (-360 ms). Unlike the previous comparison, this is a meaningful improvement.
  2. The real story is variance reduction, not raw speed. The before run had σ = 0.568 s (nearly 10% of the mean), while after has σ = 0.069 s (1.2% of the mean). That's an 8x reduction in variance. The before run had at least one outlier pushing max to 7.457 s — nearly 2 seconds above the after max.
  1. The dominant change is the count reduction on 4 rules (noGlobalEval, noGlobalIsFinite, noGlobalIsNan, noExtraBooleanCast). Their node counts dropped from ~532k to ~77k–196k. This is likely a change in which AST node types these rules subscribe to — a targeted optimization that avoids visiting irrelevant nodes.

@ematipico ematipico merged commit e7b18f7 into main May 7, 2026
33 checks passed
@ematipico ematipico deleted the perf/reduce-queries-in-rules branch May 7, 2026 13:13
@github-actions github-actions Bot mentioned this pull request May 7, 2026
OIRNOIR pushed a commit to OIRNOIR/YouTube-Helper-Server that referenced this pull request May 12, 2026
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@biomejs/biome](https://biomejs.dev) ([source](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome)) | imports | patch | [`2.4.14` -> `2.4.15`](https://renovatebot.com/diffs/npm/@biomejs%2fbiome/2.4.14/2.4.15) |

---

### Release Notes

<details>
<summary>biomejs/biome (@&#8203;biomejs/biome)</summary>

### [`v2.4.15`](https://github.com/biomejs/biome/blob/HEAD/packages/@&#8203;biomejs/biome/CHANGELOG.md#2415)

[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.4.14...@biomejs/biome@2.4.15)

##### Patch Changes

- [#&#8203;9394](biomejs/biome#9394) [`ba3480e`](biomejs/biome@ba3480e) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery rule [`useTestHooksInOrder`](https://biomejs.dev/linter/rules/use-test-hooks-in-order) in the `test` domain. The rule enforces that Jest/Vitest lifecycle hooks (`beforeAll`, `beforeEach`, `afterEach`, `afterAll`) are declared in the order they execute, making test setup and teardown easier to reason about.

- [#&#8203;10254](biomejs/biome#10254) [`e0a54cc`](biomejs/biome@e0a54cc) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added a new nursery rule [`useVueNextTickPromise`](https://biomejs.dev/linter/rules/use-vue-next-tick-promise/), which enforces Promise syntax when using Vue `nextTick`.

  For example, the following snippet triggers the rule:

  ```js
  import { nextTick } from "vue";

  nextTick(() => {
    updateDom();
  });
  ```

- [#&#8203;10219](biomejs/biome#10219) [`64aee45`](biomejs/biome@64aee45) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added a new nursery rule [`noVueVOnNumberValues`](https://biomejs.dev/linter/rules/no-vue-v-on-number-values/), that disallows deprecated number modifiers on Vue `v-on` directives.

  For example, the following snippet triggers the rule:

  ```vue
  <input @&#8203;keyup.13="submit" />
  ```

- [#&#8203;10195](biomejs/biome#10195) [`7b8d4e1`](biomejs/biome@7b8d4e1) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the new nursery rule [`useVueValidVFor`](https://biomejs.dev/linter/rules/use-vue-valid-v-for/), which validates Vue `v-for` directives and reports invalid aliases, missing component keys, and keys that do not use iteration variables.

- [#&#8203;10238](biomejs/biome#10238) [`1110256`](biomejs/biome@1110256) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the recommended nursery rule [`noVueImportCompilerMacros`](https://biomejs.dev/linter/rules/no-vue-import-compiler-macros/), which disallows importing Vue compiler macros such as `defineProps` from `vue` because they are automatically available.

- [#&#8203;10201](biomejs/biome#10201) [`1a08f89`](biomejs/biome@1a08f89) Thanks [@&#8203;realknove](https://github.com/realknove)! - Fixed [#&#8203;10193](biomejs/biome#10193): `style/useReadonlyClassProperties` no longer reports class properties as readonly-able when they are assigned inside arrow callbacks nested in class property initializers.

- [#&#8203;9574](biomejs/biome#9574) [`3bd2b6a`](biomejs/biome@3bd2b6a) Thanks [@&#8203;Conaclos](https://github.com/Conaclos)! - Fixed [#&#8203;9530](biomejs/biome#9530). The diagnostics of [`organizeImports`](https://biomejs.dev/assist/actions/organize-imports/) are now more detailed and more precise. They are also better at localizing where the issue is.

- [#&#8203;10205](biomejs/biome#10205) [`a704a6c`](biomejs/biome@a704a6c) Thanks [@&#8203;Conaclos](https://github.com/Conaclos)! - Fixed [#&#8203;10185](biomejs/biome#10185). [\`organizeImports](https://biomejs.dev/assist/actions/organize-imports/) now errors when it encounters an unknown predefined group.

  The following configuration is now reported as invalid because `:INEXISTENT:` is an unknown predefined group.

  ```json
  {
    "assist": {
      "actions": {
        "source": {
          "organizeImports": { "options": { "groups": [":INEXISTENT:"] } }
        }
      }
    }
  }
  ```

- [#&#8203;10052](biomejs/biome#10052) [`b565bed`](biomejs/biome@b565bed) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - Improved [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/): it now flags union annotations whose extra variants are never returned, and suggests the narrower type (e.g. `string | null` → `string`).

  These functions are now reported because `null` and `number` are included in the return annotations but never returned:

  ```ts
  function getUser(): string | null {
    return "hello";
  } // null is never returned
  function getCode(): string | number {
    return "hello";
  } // number is never returned
  ```

- [#&#8203;10213](biomejs/biome#10213) [`ac30057`](biomejs/biome@ac30057) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;9450](biomejs/biome#9450): HTML and Vue element formatting now preserves child line breaks when an element contains another element child on its own line, instead of collapsing the child element onto the same line.

- [#&#8203;10275](biomejs/biome#10275) [`9ee6c03`](biomejs/biome@9ee6c03) Thanks [@&#8203;solithcy](https://github.com/solithcy)! - Fixed [#&#8203;10274](biomejs/biome#10274): Svelte templates with missing expressions no longer parsed as `HtmlBogusElement`

- [#&#8203;10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) now detects misleading return type annotations when object literal properties are initialized with `as const`.

  This function is now reported because the return annotation widens a property initialized with `as const`:

  ```ts
  function f(): { value: string } {
    return { value: "text" as const };
  }
  ```

- [#&#8203;10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - [`noUselessTypeConversion`](https://biomejs.dev/linter/rules/no-useless-type-conversion/) now detects redundant conversions on object literal properties initialized with `as const`.

  This conversion is now reported because `message.value` is inferred as a string literal:

  ```ts
  const message = { value: "text" as const };
  String(message.value);
  ```

- [#&#8203;9807](biomejs/biome#9807) [`0ae5840`](biomejs/biome@0ae5840) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the new nursery rule [`useThisInClassMethods`](https://biomejs.dev/linter/rules/use-this-in-class-methods/), based on ESLint's `class-methods-use-this`.

  The rule now reports instance methods, getters, setters, and function-valued instance fields that do not use `this`, and `biome migrate eslint` preserves the supported `ignoreMethods`, `ignoreOverrideMethods`, and `ignoreClassesWithImplements` options.

  **Invalid**:

  ```js
  class Foo {
    bar() {
      // does not use `this`, invalid
      console.log("Hello Biome");
    }
  }
  ```

- [#&#8203;10258](biomejs/biome#10258) [`e7b18f7`](biomejs/biome@e7b18f7) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Improved linter performance by narrowing the query nodes for several lint rules, reducing how often they are evaluated.

- [#&#8203;10273](biomejs/biome#10273) [`04e22a1`](biomejs/biome@04e22a1) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;10271](biomejs/biome#10271): The HTML parser now correctly parses `of` as text content when in text contexts.

- [#&#8203;9838](biomejs/biome#9838) [`83f7385`](biomejs/biome@83f7385) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery rule [`noBaseToString`](https://biomejs.dev/linter/rules/no-base-to-string/), which reports stringification sites that fall back to Object's default `"[object Object]"` formatting. The rule also supports the `ignoredTypeNames` option.

- [#&#8203;10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - [`useExhaustiveSwitchCases`](https://biomejs.dev/linter/rules/use-exhaustive-switch-cases/) now checks switch statements over object literal properties initialized with `as const`.

  This switch is now reported because `status.kind` is inferred as the string literal `"ready"` but no case handles it:

  ```ts
  const status = { kind: "ready" as const };
  switch (status.kind) {
  }
  ```

- [#&#8203;10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - [`useStringStartsEndsWith`](https://biomejs.dev/linter/rules/use-string-starts-ends-with/) now detects string index comparisons on object literal properties initialized with `as const`.

  This comparison is now reported because `message.value` is inferred as a string literal:

  ```ts
  const message = { value: "hello" as const };
  message.value[0] === "h";
  ```

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNzMuMyIsInVwZGF0ZWRJblZlciI6IjQzLjE3My4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://git.oirnoir.dev/OIRNOIR/YouTube-Helper-Server/pulls/12
OIRNOIR pushed a commit to OIRNOIR/YouTube-Helper-Client that referenced this pull request May 13, 2026
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@biomejs/biome](https://biomejs.dev) ([source](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome)) | imports | patch | [`2.4.14` -> `2.4.15`](https://renovatebot.com/diffs/npm/@biomejs%2fbiome/2.4.14/2.4.15) |

---

### Release Notes

<details>
<summary>biomejs/biome (@&#8203;biomejs/biome)</summary>

### [`v2.4.15`](https://github.com/biomejs/biome/blob/HEAD/packages/@&#8203;biomejs/biome/CHANGELOG.md#2415)

[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.4.14...@biomejs/biome@2.4.15)

##### Patch Changes

- [#&#8203;9394](biomejs/biome#9394) [`ba3480e`](biomejs/biome@ba3480e) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery rule [`useTestHooksInOrder`](https://biomejs.dev/linter/rules/use-test-hooks-in-order) in the `test` domain. The rule enforces that Jest/Vitest lifecycle hooks (`beforeAll`, `beforeEach`, `afterEach`, `afterAll`) are declared in the order they execute, making test setup and teardown easier to reason about.

- [#&#8203;10254](biomejs/biome#10254) [`e0a54cc`](biomejs/biome@e0a54cc) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added a new nursery rule [`useVueNextTickPromise`](https://biomejs.dev/linter/rules/use-vue-next-tick-promise/), which enforces Promise syntax when using Vue `nextTick`.

  For example, the following snippet triggers the rule:

  ```js
  import { nextTick } from "vue";

  nextTick(() => {
    updateDom();
  });
  ```

- [#&#8203;10219](biomejs/biome#10219) [`64aee45`](biomejs/biome@64aee45) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added a new nursery rule [`noVueVOnNumberValues`](https://biomejs.dev/linter/rules/no-vue-v-on-number-values/), that disallows deprecated number modifiers on Vue `v-on` directives.

  For example, the following snippet triggers the rule:

  ```vue
  <input @&#8203;keyup.13="submit" />
  ```

- [#&#8203;10195](biomejs/biome#10195) [`7b8d4e1`](biomejs/biome@7b8d4e1) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the new nursery rule [`useVueValidVFor`](https://biomejs.dev/linter/rules/use-vue-valid-v-for/), which validates Vue `v-for` directives and reports invalid aliases, missing component keys, and keys that do not use iteration variables.

- [#&#8203;10238](biomejs/biome#10238) [`1110256`](biomejs/biome@1110256) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the recommended nursery rule [`noVueImportCompilerMacros`](https://biomejs.dev/linter/rules/no-vue-import-compiler-macros/), which disallows importing Vue compiler macros such as `defineProps` from `vue` because they are automatically available.

- [#&#8203;10201](biomejs/biome#10201) [`1a08f89`](biomejs/biome@1a08f89) Thanks [@&#8203;realknove](https://github.com/realknove)! - Fixed [#&#8203;10193](biomejs/biome#10193): `style/useReadonlyClassProperties` no longer reports class properties as readonly-able when they are assigned inside arrow callbacks nested in class property initializers.

- [#&#8203;9574](biomejs/biome#9574) [`3bd2b6a`](biomejs/biome@3bd2b6a) Thanks [@&#8203;Conaclos](https://github.com/Conaclos)! - Fixed [#&#8203;9530](biomejs/biome#9530). The diagnostics of [`organizeImports`](https://biomejs.dev/assist/actions/organize-imports/) are now more detailed and more precise. They are also better at localizing where the issue is.

- [#&#8203;10205](biomejs/biome#10205) [`a704a6c`](biomejs/biome@a704a6c) Thanks [@&#8203;Conaclos](https://github.com/Conaclos)! - Fixed [#&#8203;10185](biomejs/biome#10185). [\`organizeImports](https://biomejs.dev/assist/actions/organize-imports/) now errors when it encounters an unknown predefined group.

  The following configuration is now reported as invalid because `:INEXISTENT:` is an unknown predefined group.

  ```json
  {
    "assist": {
      "actions": {
        "source": {
          "organizeImports": { "options": { "groups": [":INEXISTENT:"] } }
        }
      }
    }
  }
  ```

- [#&#8203;10052](biomejs/biome#10052) [`b565bed`](biomejs/biome@b565bed) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - Improved [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/): it now flags union annotations whose extra variants are never returned, and suggests the narrower type (e.g. `string | null` → `string`).

  These functions are now reported because `null` and `number` are included in the return annotations but never returned:

  ```ts
  function getUser(): string | null {
    return "hello";
  } // null is never returned
  function getCode(): string | number {
    return "hello";
  } // number is never returned
  ```

- [#&#8203;10213](biomejs/biome#10213) [`ac30057`](biomejs/biome@ac30057) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;9450](biomejs/biome#9450): HTML and Vue element formatting now preserves child line breaks when an element contains another element child on its own line, instead of collapsing the child element onto the same line.

- [#&#8203;10275](biomejs/biome#10275) [`9ee6c03`](biomejs/biome@9ee6c03) Thanks [@&#8203;solithcy](https://github.com/solithcy)! - Fixed [#&#8203;10274](biomejs/biome#10274): Svelte templates with missing expressions no longer parsed as `HtmlBogusElement`

- [#&#8203;10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) now detects misleading return type annotations when object literal properties are initialized with `as const`.

  This function is now reported because the return annotation widens a property initialized with `as const`:

  ```ts
  function f(): { value: string } {
    return { value: "text" as const };
  }
  ```

- [#&#8203;10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - [`noUselessTypeConversion`](https://biomejs.dev/linter/rules/no-useless-type-conversion/) now detects redundant conversions on object literal properties initialized with `as const`.

  This conversion is now reported because `message.value` is inferred as a string literal:

  ```ts
  const message = { value: "text" as const };
  String(message.value);
  ```

- [#&#8203;9807](biomejs/biome#9807) [`0ae5840`](biomejs/biome@0ae5840) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the new nursery rule [`useThisInClassMethods`](https://biomejs.dev/linter/rules/use-this-in-class-methods/), based on ESLint's `class-methods-use-this`.

  The rule now reports instance methods, getters, setters, and function-valued instance fields that do not use `this`, and `biome migrate eslint` preserves the supported `ignoreMethods`, `ignoreOverrideMethods`, and `ignoreClassesWithImplements` options.

  **Invalid**:

  ```js
  class Foo {
    bar() {
      // does not use `this`, invalid
      console.log("Hello Biome");
    }
  }
  ```

- [#&#8203;10258](biomejs/biome#10258) [`e7b18f7`](biomejs/biome@e7b18f7) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Improved linter performance by narrowing the query nodes for several lint rules, reducing how often they are evaluated.

- [#&#8203;10273](biomejs/biome#10273) [`04e22a1`](biomejs/biome@04e22a1) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;10271](biomejs/biome#10271): The HTML parser now correctly parses `of` as text content when in text contexts.

- [#&#8203;9838](biomejs/biome#9838) [`83f7385`](biomejs/biome@83f7385) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery rule [`noBaseToString`](https://biomejs.dev/linter/rules/no-base-to-string/), which reports stringification sites that fall back to Object's default `"[object Object]"` formatting. The rule also supports the `ignoredTypeNames` option.

- [#&#8203;10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - [`useExhaustiveSwitchCases`](https://biomejs.dev/linter/rules/use-exhaustive-switch-cases/) now checks switch statements over object literal properties initialized with `as const`.

  This switch is now reported because `status.kind` is inferred as the string literal `"ready"` but no case handles it:

  ```ts
  const status = { kind: "ready" as const };
  switch (status.kind) {
  }
  ```

- [#&#8203;10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - [`useStringStartsEndsWith`](https://biomejs.dev/linter/rules/use-string-starts-ends-with/) now detects string index comparisons on object literal properties initialized with `as const`.

  This comparison is now reported because `message.value` is inferred as a string literal:

  ```ts
  const message = { value: "hello" as const };
  message.value[0] === "h";
  ```

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNzMuMyIsInVwZGF0ZWRJblZlciI6IjQzLjE3My4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://git.oirnoir.dev/OIRNOIR/YouTube-Helper-Client/pulls/3
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-CSS Language: CSS and super languages L-JavaScript Language: JavaScript and super languages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants