fix(analyzer): useReadonlyClassProperties detects non-declaration class forms#10105
Conversation
…on-declaration classes Covers three forms currently missed by the rule: - anonymous class expression assigned to a variable - named class expression assigned to a variable - anonymous export default class All three share the same root cause: the SemanticClass service visitor only matches `JsClassDeclaration`, so the rule never runs on these nodes. The fixture uses `should generate diagnostics` so the test harness enforces the expectation. Refs biomejs#10039.
…ss forms The `SemanticClass` service visitor matched only `JsClassDeclaration`, so class expressions and export default classes were silently skipped by the rule. Widen the visitor and the rule's query to `AnyJsClass`, which covers all three class forms. The rule already calls only `AnyJsClass`-available methods (`members`), so no further refactor is needed. Existing nested class expression fixtures in `invalid.ts` now produce diagnostics as expected — four new entries appear in the updated snapshot. Fixes biomejs#10039.
🦋 Changeset detectedLatest commit: 331c3d0 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 |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (2)
📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThe Suggested labels
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🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
crates/biome_js_analyze/src/services/semantic_class.rs (1)
271-279: Worth a quick sanity check:JS_CLASS_EXPORT_DEFAULT_DECLARATIONisn't in the skip-list.Now that
AnyJsClassis queried, the rule can be entered on anexport default class. Here inThisScopeVisitor::visit(and inis_within_scope_without_shadowingat lines 875-880) we only treatJS_CLASS_EXPRESSIONandJS_CLASS_DECLARATIONas class-scope boundaries. In practice a nestedexport default classshouldn't appear inside another class body (export is module-level), so this is likely a non-issue — but it's an easy footgun if that ever changes. A belt-and-braces addition would keep the three variants in lock-step withAnyJsClass::KIND_SET.🛡️ Optional hardening
- if node.kind() == JsSyntaxKind::JS_CLASS_EXPRESSION { - self.skipped_ranges.push(node.text_range()); - return; - } - - if node.kind() == JsSyntaxKind::JS_CLASS_DECLARATION { - self.skipped_ranges.push(node.text_range()); - return; - } + if matches!( + node.kind(), + JsSyntaxKind::JS_CLASS_EXPRESSION + | JsSyntaxKind::JS_CLASS_DECLARATION + | JsSyntaxKind::JS_CLASS_EXPORT_DEFAULT_DECLARATION + ) { + self.skipped_ranges.push(node.text_range()); + return; + }And analogously in
is_within_scope_without_shadowing.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_analyze/src/services/semantic_class.rs` around lines 271 - 279, The skip-list currently only checks for JsSyntaxKind::JS_CLASS_EXPRESSION and JsSyntaxKind::JS_CLASS_DECLARATION in ThisScopeVisitor::visit (and similarly in is_within_scope_without_shadowing), but misses JsSyntaxKind::JS_CLASS_EXPORT_DEFAULT_DECLARATION; update both places to also treat JS_CLASS_EXPORT_DEFAULT_DECLARATION as a class-scope boundary so the logic stays consistent with AnyJsClass::KIND_SET and avoids unexpected behavior for `export default class`.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@crates/biome_js_analyze/src/lint/style/use_readonly_class_properties.rs`:
- Line 127: You changed the Query type to use SemanticClass<AnyJsClass>, which
requires regenerating rule artifacts; before finalizing the PR run the codegen
pipeline by executing `just gen-rules` followed by `just gen-configuration` so
the generated outputs for this *_analyze crate are updated to reflect the Query
type change (no code changes needed to run/diagnostic/action or fix_kind:
FixKind::Unsafe).
In
`@crates/biome_js_analyze/tests/specs/style/useReadonlyClassProperties/invalid_classExpression.ts`:
- Around line 3-5: The header comment mentions "export default classes
(anonymous and named)" but the fixture only contains an anonymous export default
class; either remove "and named" from the comment or add a named export default
class test case (e.g., add an `export default class Foo { /* same private field
usage as other cases */ }` case) so the header and fixtures match; locate the
test file and update the header or add the `export default class Foo` class
expression to mirror the anonymous export-default case.
---
Nitpick comments:
In `@crates/biome_js_analyze/src/services/semantic_class.rs`:
- Around line 271-279: The skip-list currently only checks for
JsSyntaxKind::JS_CLASS_EXPRESSION and JsSyntaxKind::JS_CLASS_DECLARATION in
ThisScopeVisitor::visit (and similarly in is_within_scope_without_shadowing),
but misses JsSyntaxKind::JS_CLASS_EXPORT_DEFAULT_DECLARATION; update both places
to also treat JS_CLASS_EXPORT_DEFAULT_DECLARATION as a class-scope boundary so
the logic stays consistent with AnyJsClass::KIND_SET and avoids unexpected
behavior for `export default class`.
🪄 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: c39d6a6e-2ca1-4b44-bd92-685eb58dbee2
⛔ Files ignored due to path filters (2)
crates/biome_js_analyze/tests/specs/style/useReadonlyClassProperties/invalid.ts.snapis excluded by!**/*.snapand included by**crates/biome_js_analyze/tests/specs/style/useReadonlyClassProperties/invalid_classExpression.ts.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (4)
.changeset/red-cloths-bake.mdcrates/biome_js_analyze/src/lint/style/use_readonly_class_properties.rscrates/biome_js_analyze/src/services/semantic_class.rscrates/biome_js_analyze/tests/specs/style/useReadonlyClassProperties/invalid_classExpression.ts
Merging this PR will not alter performance
Comparing Footnotes
|
…perties Splits out into a sibling fixture since a module can only contain a single `export default`. Clarifies the header of the original fixture to match the cases it actually tests. Addresses review feedback on biomejs#10105.
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.13` -> `2.4.14`](https://renovatebot.com/diffs/npm/@biomejs%2fbiome/2.4.13/2.4.14) | --- ### Release Notes <details> <summary>biomejs/biome (@​biomejs/biome)</summary> ### [`v2.4.14`](https://github.com/biomejs/biome/blob/HEAD/packages/@​biomejs/biome/CHANGELOG.md#2414) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.4.13...@biomejs/biome@2.4.14) ##### Patch Changes - [#​9393](biomejs/biome#9393) [`491b171`](biomejs/biome@491b171) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`useTestHooksOnTop`](https://biomejs.dev/linter/rules/use-test-hooks-on-top) in the `test` domain. The rule flags lifecycle hooks (`beforeEach`, `beforeAll`, `afterEach`, `afterAll`) that appear after test cases in the same block, enforcing that hooks are defined before any test case. - [#​10157](biomejs/biome#10157) [`eefc5ab`](biomejs/biome@eefc5ab) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​7882](biomejs/biome#7882): The HTML parser will now emit better diagnostics when it encounters a void element with a closing tag, such as `<br></br>`. Previously, the parser would emit multiple diagnostics with conflicting advice. Now it emits a single diagnostic that clearly states that void elements should not have closing tags. - [#​10054](biomejs/biome#10054) [`0e9f569`](biomejs/biome@0e9f569) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) no longer misses widening from concrete object types, class instances, object literals, tuples, functions, and regular expressions to `: object`. A function annotated `: object` returning an object literal: ```ts function f(): object { return { retry: true }; } ``` - [#​10116](biomejs/biome#10116) [`53269eb`](biomejs/biome@53269eb) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​6201](biomejs/biome#6201): [`noUselessEscapeInRegex`](https://biomejs.dev/linter/rules/no-useless-escape-in-regex/) no longer flags an escaped backslash followed by `-` as a useless escape. Patterns like `/[\\-]/` are now considered valid because the second `\` is the escaped backslash, not an unnecessary escape of the trailing dash. - [#​10092](biomejs/biome#10092) [`33d8543`](biomejs/biome@33d8543) Thanks [@​Conaclos](https://github.com/Conaclos)! - Fixed [#​9097](biomejs/biome#9097): [`organizeImports`](https://biomejs.dev/assist/actions/organize-imports/) no longer adds a blank line between a never-matched group and a matched group. Given the following `organizeImports` options: ```json { "groups": [":NODE:", ":BLANK_LINE:", ":PACKAGE:", ":BLANK_LINE:", ":PATH:"] } ``` The following code... ```js // Comment import "package"; import "./file.js"; ``` ...was organized as: ```diff + // Comment import "package"; + import "./file.js"; ``` A blank line was added even though the group ':NODE:' doesn't match any imports here. `:BLANK_LINE:` between never-matched groups and matched groups are now ignored. The code is now organized as: ```diff // Comment import "package"; + import "./file.js"; ``` - [#​10138](biomejs/biome#10138) [`a10b6c1`](biomejs/biome@a10b6c1) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed Vue `v-for` handling for [`noUndeclaredVariables`](https://biomejs.dev/linter/rules/no-undeclared-variables/) and [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/). Biome now recognizes variables declared by `v-for` directives and references to iterated values in Vue templates. - [#​10115](biomejs/biome#10115) [`d428d76`](biomejs/biome@d428d76) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) no longer reports false positives when a union return type's `boolean` variant is covered by both `true` and `false` returns. - [#​9922](biomejs/biome#9922) [`7acf1e0`](biomejs/biome@7acf1e0) Thanks [@​dyc3](https://github.com/dyc3)! - Added the new nursery rule [`noReactStringRefs`](https://biomejs.dev/linter/rules/no-react-string-refs/), which disallows legacy React string refs such as `ref="hello"` and `this.refs.hello`. Biome also reports template-literal refs such as ``ref={`hello`}``, so React code can consistently migrate to callback refs, `createRef()`, or `useRef()`. - [#​10010](biomejs/biome#10010) [`f3e76ab`](biomejs/biome@f3e76ab) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed a bug in the LSP file watcher registration so Biome now watches `.biome.json` and `.biome.jsonc` configuration files and reloads workspace settings when they change. - [#​10176](biomejs/biome#10176) [`8a40ef8`](biomejs/biome@8a40ef8) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10011](biomejs/biome#10011): The [`noThisInStatic`](https://biomejs.dev/linter/rules/no-this-in-static/) rule no longer reports `this` when it is used as the constructor target in `new this(...)`, which is required for inherited static factory methods. - [#​10163](biomejs/biome#10163) [`6867e96`](biomejs/biome@6867e96) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​9884](biomejs/biome#9884): The [`useSortedAttributes`](https://biomejs.dev/assist/actions/use-sorted-attributes/) auto-fix no longer corrupts source code when both an outer JSX element and a nested JSX-valued attribute have unsorted attributes in the same pass. Multiple unsorted groups separated by spread or shorthand attributes within the same JSX element are now reported as a single diagnostic. - [#​10079](biomejs/biome#10079) [`d29dd19`](biomejs/biome@d29dd19) Thanks [@​Damix48](https://github.com/Damix48)! - Fixed false positive in `noAssignInExpressions` for Svelte `{@​const}` blocks. Assignments in `{@​const name = value}` are now correctly recognized as declarations rather than accidental assignments in expressions. - [#​10080](biomejs/biome#10080) [`5d8fdac`](biomejs/biome@5d8fdac) Thanks [@​Damix48](https://github.com/Damix48)! - Fixed parsing of closing parentheses in Svelte `{#each}` block key expressions. Biome now correctly parses method calls and other parenthesised expressions used as keys. For example, the following snippets are now parsed correctly: ```svelte {#each numbers as number, index (number.toString())} <p>{number}</p> {/each} {#each numbers as number (key(number))} <p>{number}</p> {/each} ``` - [#​10140](biomejs/biome#10140) [`e7024b9`](biomejs/biome@e7024b9) Thanks [@​solithcy](https://github.com/solithcy)! - Fixed [#​10135](biomejs/biome#10135): Biome no longer crashes on missing Svelte template expressions. The following code snippet longer panics: ```svelte {#if } <p>^ this would previously crash</p> {/if} {@​const } <p> ^ this would also crash</p> ``` - [#​10111](biomejs/biome#10111) [`7818009`](biomejs/biome@7818009) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​9997](biomejs/biome#9997): [`noDuplicateSelectors`](https://biomejs.dev/linter/rules/no-duplicate-selectors/) no longer reports false positives for selectors inside `@scope` queries. Biome now treats `@scope` as a separate at-rule context, like `@media`, `@supports`, `@container`, and `@starting-style`. The following snippet is no longer flagged as a duplicate: ```css .Example { padding: 0; } @​scope (.theme-dark) { .Example { color: white; } } ``` - [#​9926](biomejs/biome#9926) [`d62b331`](biomejs/biome@d62b331) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery lint rule [`useMathMinMax`](https://biomejs.dev/linter/rules/use-math-min-max/), which prefers `Math.min()` and `Math.max()` over equivalent ternary comparisons. For example, this code: ```js const min = a < b ? a : b; ``` is much more readable when rewritten as: ```js const min = Math.min(a, b); ``` - [#​10115](biomejs/biome#10115) [`d428d76`](biomejs/biome@d428d76) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`useExhaustiveSwitchCases`](https://biomejs.dev/linter/rules/use-exhaustive-switch-cases/) now flags missing `true`/`false` cases for `boolean` discriminants, including when `boolean` is a union variant. - [#​10125](biomejs/biome#10125) [`a55a0b6`](biomejs/biome@a55a0b6) Thanks [@​bmish](https://github.com/bmish)! - Fixed a resolver bug where packages that define a typed entry point through `package.json`'s `main` field but omit `types` were ignored during type-aware resolution. Type-aware rules such as [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) can now inspect imports from those packages. - [#​10117](biomejs/biome#10117) [`895e809`](biomejs/biome@895e809) Thanks [@​denizdogan](https://github.com/denizdogan)! - Added support for the `corner-shape` family of CSS properties and the `superellipse()`/`squircle()` value functions, so [`noUnknownProperty`](https://biomejs.dev/linter/rules/no-unknown-property/) and [`noUnknownFunction`](https://biomejs.dev/linter/rules/no-unknown-function/) no longer flag them as unknown. New known properties: `corner-shape`, `corner-block-end-shape`, `corner-block-start-shape`, `corner-bottom-left-shape`, `corner-bottom-right-shape`, `corner-bottom-shape`, `corner-end-end-shape`, `corner-end-start-shape`, `corner-inline-end-shape`, `corner-inline-start-shape`, `corner-left-shape`, `corner-right-shape`, `corner-start-end-shape`, `corner-start-start-shape`, `corner-top-left-shape`, `corner-top-right-shape`, `corner-top-shape`. New known value functions: `superellipse()`, `squircle()`. - [#​8620](biomejs/biome#8620) [`8df8f73`](biomejs/biome@8df8f73) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​8062](biomejs/biome#8062): Added support for parsing Vue `v-for` directives more accurately. - [#​10191](biomejs/biome#10191) [`aa055cd`](biomejs/biome@aa055cd) Thanks [@​guney](https://github.com/guney)! - Now the rule [`noStaticElementInteractions`](https://biomejs.dev/linter/rules/no-static-element-interactions/) doesn't trigger custom elements. - [#​9757](biomejs/biome#9757) [`2c62594`](biomejs/biome@2c62594) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​9099](biomejs/biome#9099): the HTML formatter collapsing non-text children (inline elements, Svelte expressions, comments) onto a single line when the source had them on separate lines. Biome now preserves the user's intended line breaks for exclusively non-text children. For example, the following Svelte snippet is now preserved instead of being collapsed to `<div>{name}<!-- comment --></div>`: ```svelte <div> {name}<!-- comment --> </div> ``` Similarly, HTML elements like `<span>` inside a `<div>` are now preserved when written on their own line: ```html <div> <span>text</span> </div> ``` - [#​10105](biomejs/biome#10105) [`e7c1a6d`](biomejs/biome@e7c1a6d) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​10039](biomejs/biome#10039): [`useReadonlyClassProperties`](https://biomejs.dev/linter/rules/use-readonly-class-properties/) now detects unreassigned private members in class expressions and export default classes, not only in class declarations. The following patterns are now correctly flagged: ```ts const AnonClass = class { #prop = 123; constructor() { console.log(this.#prop); } }; export default class { #prop = 123; constructor() { console.log(this.#prop); } } ``` - [#​10141](biomejs/biome#10141) [`46a77d0`](biomejs/biome@46a77d0) Thanks [@​minseong0324](https://github.com/minseong0324)! - Improved [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/) to detect conditions that are always truthy because they check built-in global class instances such as `Date`, `Map`, `Set`, `WeakMap`, and `Error`. - [#​10178](biomejs/biome#10178) [`7b05a89`](biomejs/biome@7b05a89) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10177](biomejs/biome#10177): The HTML parser no longer reports lowercase `html` or `doctype` text as invalid after void elements such as `<br>`. - [#​10155](biomejs/biome#10155) [`0d4595d`](biomejs/biome@0d4595d) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​10045](biomejs/biome#10045): the CSS formatter no longer compounds indentation inside nested functional pseudo-classes such as `:not(:where(...))`, `:is(:where(...))`, and similar combinations. The same fix also removes one level of unnecessary indentation that was added inside any pseudo-class function whose argument list wrapped onto multiple lines, including `:nth-child(... of ...)`, `::part(...)`, and `:active-view-transition-type(...)`. The following snippet is now correctly formatted, matching Prettier. ```css input:not( :where( [type="submit"], [type="checkbox"], [type="radio"], [type="button"], [type="reset"] ) ) { inline-size: 100%; } ``` - [#​10112](biomejs/biome#10112) [`6f0251e`](biomejs/biome@6f0251e) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10110](biomejs/biome#10110): Biome's parser now accepts surrogate code points in JavaScript string `\u{...}` escapes. - [#​10141](biomejs/biome#10141) [`46a77d0`](biomejs/biome@46a77d0) Thanks [@​minseong0324](https://github.com/minseong0324)! - Improved [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) to detect `object` return annotations that hide built-in global class instances such as `Date`, `Map`, `Set`, `WeakMap`, and `Error`. - [#​10083](biomejs/biome#10083) [`4a664c1`](biomejs/biome@4a664c1) Thanks [@​ematipico](https://github.com/ematipico)! - Added two new options to [`noShadow`](https://biomejs.dev/linter/rules/no-shadow/), both defaulting to `true` to match typescript-eslint's behavior. Fixed [#​9482](biomejs/biome#9482): Added `ignoreFunctionTypeParameterNameValueShadow` option. When enabled, parameter names inside function type annotations (e.g. `(options: unknown) => void`) are not flagged as shadowing outer variables. Fixed [#​7812](biomejs/biome#7812): Added `ignoreTypeValueShadow` option. When enabled, a value binding that shares its name with a type-only declaration (type alias or interface) is not flagged, since types and values occupy separate namespaces in TypeScript. - [#​9286](biomejs/biome#9286) [`52695cf`](biomejs/biome@52695cf) Thanks [@​Hugo-Polloli](https://github.com/Hugo-Polloli)! - Fixed [#​6316](biomejs/biome#6316): Biome now resolves Svelte `$store` references to the underlying `store` binding in semantic analysis, preventing false `noUndeclaredVariables` diagnostics when the store is declared. - [#​10188](biomejs/biome#10188) [`ae659dd`](biomejs/biome@ae659dd) Thanks [@​dyc3](https://github.com/dyc3)! - Added a new nursery rule [`noExcessiveNestedCallbacks`](https://biomejs.dev/linter/rules/no-excessive-nested-callbacks/), which disallows callbacks nested deeper than the configured maximum. - [#​9757](biomejs/biome#9757) [`2c62594`](biomejs/biome@2c62594) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​9450](biomejs/biome#9450): the HTML formatter now correctly preserves multiline formatting for nested `<template>` elements (e.g. `<template #body>`) when the source has children on separate lines. Previously, the children were collapsed onto a single line. ```diff <template> <UModal> - <template #body> <p>content</p> </template> + <template #body> + <p>content</p> + </template> </UModal> </template> ``` - [#​10118](biomejs/biome#10118) [`c6edcb4`](biomejs/biome@c6edcb4) Thanks [@​Netail](https://github.com/Netail)! - Fixed [#​10024](biomejs/biome#10024): `biome migrate eslint` correctly migrates `eslint` rules that belong to multiple Biome rules. </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:eyJjcmVhdGVkSW5WZXIiOiI0My4xNjAuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE2MC4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://git.oirnoir.dev/OIRNOIR/YouTube-Helper-Client/pulls/2
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.13` -> `2.4.14`](https://renovatebot.com/diffs/npm/@biomejs%2fbiome/2.4.13/2.4.14) | --- ### Release Notes <details> <summary>biomejs/biome (@​biomejs/biome)</summary> ### [`v2.4.14`](https://github.com/biomejs/biome/blob/HEAD/packages/@​biomejs/biome/CHANGELOG.md#2414) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.4.13...@biomejs/biome@2.4.14) ##### Patch Changes - [#​9393](biomejs/biome#9393) [`491b171`](biomejs/biome@491b171) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`useTestHooksOnTop`](https://biomejs.dev/linter/rules/use-test-hooks-on-top) in the `test` domain. The rule flags lifecycle hooks (`beforeEach`, `beforeAll`, `afterEach`, `afterAll`) that appear after test cases in the same block, enforcing that hooks are defined before any test case. - [#​10157](biomejs/biome#10157) [`eefc5ab`](biomejs/biome@eefc5ab) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​7882](biomejs/biome#7882): The HTML parser will now emit better diagnostics when it encounters a void element with a closing tag, such as `<br></br>`. Previously, the parser would emit multiple diagnostics with conflicting advice. Now it emits a single diagnostic that clearly states that void elements should not have closing tags. - [#​10054](biomejs/biome#10054) [`0e9f569`](biomejs/biome@0e9f569) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) no longer misses widening from concrete object types, class instances, object literals, tuples, functions, and regular expressions to `: object`. A function annotated `: object` returning an object literal: ```ts function f(): object { return { retry: true }; } ``` - [#​10116](biomejs/biome#10116) [`53269eb`](biomejs/biome@53269eb) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​6201](biomejs/biome#6201): [`noUselessEscapeInRegex`](https://biomejs.dev/linter/rules/no-useless-escape-in-regex/) no longer flags an escaped backslash followed by `-` as a useless escape. Patterns like `/[\\-]/` are now considered valid because the second `\` is the escaped backslash, not an unnecessary escape of the trailing dash. - [#​10092](biomejs/biome#10092) [`33d8543`](biomejs/biome@33d8543) Thanks [@​Conaclos](https://github.com/Conaclos)! - Fixed [#​9097](biomejs/biome#9097): [`organizeImports`](https://biomejs.dev/assist/actions/organize-imports/) no longer adds a blank line between a never-matched group and a matched group. Given the following `organizeImports` options: ```json { "groups": [":NODE:", ":BLANK_LINE:", ":PACKAGE:", ":BLANK_LINE:", ":PATH:"] } ``` The following code... ```js // Comment import "package"; import "./file.js"; ``` ...was organized as: ```diff + // Comment import "package"; + import "./file.js"; ``` A blank line was added even though the group ':NODE:' doesn't match any imports here. `:BLANK_LINE:` between never-matched groups and matched groups are now ignored. The code is now organized as: ```diff // Comment import "package"; + import "./file.js"; ``` - [#​10138](biomejs/biome#10138) [`a10b6c1`](biomejs/biome@a10b6c1) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed Vue `v-for` handling for [`noUndeclaredVariables`](https://biomejs.dev/linter/rules/no-undeclared-variables/) and [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/). Biome now recognizes variables declared by `v-for` directives and references to iterated values in Vue templates. - [#​10115](biomejs/biome#10115) [`d428d76`](biomejs/biome@d428d76) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) no longer reports false positives when a union return type's `boolean` variant is covered by both `true` and `false` returns. - [#​9922](biomejs/biome#9922) [`7acf1e0`](biomejs/biome@7acf1e0) Thanks [@​dyc3](https://github.com/dyc3)! - Added the new nursery rule [`noReactStringRefs`](https://biomejs.dev/linter/rules/no-react-string-refs/), which disallows legacy React string refs such as `ref="hello"` and `this.refs.hello`. Biome also reports template-literal refs such as ``ref={`hello`}``, so React code can consistently migrate to callback refs, `createRef()`, or `useRef()`. - [#​10010](biomejs/biome#10010) [`f3e76ab`](biomejs/biome@f3e76ab) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed a bug in the LSP file watcher registration so Biome now watches `.biome.json` and `.biome.jsonc` configuration files and reloads workspace settings when they change. - [#​10176](biomejs/biome#10176) [`8a40ef8`](biomejs/biome@8a40ef8) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10011](biomejs/biome#10011): The [`noThisInStatic`](https://biomejs.dev/linter/rules/no-this-in-static/) rule no longer reports `this` when it is used as the constructor target in `new this(...)`, which is required for inherited static factory methods. - [#​10163](biomejs/biome#10163) [`6867e96`](biomejs/biome@6867e96) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​9884](biomejs/biome#9884): The [`useSortedAttributes`](https://biomejs.dev/assist/actions/use-sorted-attributes/) auto-fix no longer corrupts source code when both an outer JSX element and a nested JSX-valued attribute have unsorted attributes in the same pass. Multiple unsorted groups separated by spread or shorthand attributes within the same JSX element are now reported as a single diagnostic. - [#​10079](biomejs/biome#10079) [`d29dd19`](biomejs/biome@d29dd19) Thanks [@​Damix48](https://github.com/Damix48)! - Fixed false positive in `noAssignInExpressions` for Svelte `{@​const}` blocks. Assignments in `{@​const name = value}` are now correctly recognized as declarations rather than accidental assignments in expressions. - [#​10080](biomejs/biome#10080) [`5d8fdac`](biomejs/biome@5d8fdac) Thanks [@​Damix48](https://github.com/Damix48)! - Fixed parsing of closing parentheses in Svelte `{#each}` block key expressions. Biome now correctly parses method calls and other parenthesised expressions used as keys. For example, the following snippets are now parsed correctly: ```svelte {#each numbers as number, index (number.toString())} <p>{number}</p> {/each} {#each numbers as number (key(number))} <p>{number}</p> {/each} ``` - [#​10140](biomejs/biome#10140) [`e7024b9`](biomejs/biome@e7024b9) Thanks [@​solithcy](https://github.com/solithcy)! - Fixed [#​10135](biomejs/biome#10135): Biome no longer crashes on missing Svelte template expressions. The following code snippet longer panics: ```svelte {#if } <p>^ this would previously crash</p> {/if} {@​const } <p> ^ this would also crash</p> ``` - [#​10111](biomejs/biome#10111) [`7818009`](biomejs/biome@7818009) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​9997](biomejs/biome#9997): [`noDuplicateSelectors`](https://biomejs.dev/linter/rules/no-duplicate-selectors/) no longer reports false positives for selectors inside `@scope` queries. Biome now treats `@scope` as a separate at-rule context, like `@media`, `@supports`, `@container`, and `@starting-style`. The following snippet is no longer flagged as a duplicate: ```css .Example { padding: 0; } @​scope (.theme-dark) { .Example { color: white; } } ``` - [#​9926](biomejs/biome#9926) [`d62b331`](biomejs/biome@d62b331) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery lint rule [`useMathMinMax`](https://biomejs.dev/linter/rules/use-math-min-max/), which prefers `Math.min()` and `Math.max()` over equivalent ternary comparisons. For example, this code: ```js const min = a < b ? a : b; ``` is much more readable when rewritten as: ```js const min = Math.min(a, b); ``` - [#​10115](biomejs/biome#10115) [`d428d76`](biomejs/biome@d428d76) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`useExhaustiveSwitchCases`](https://biomejs.dev/linter/rules/use-exhaustive-switch-cases/) now flags missing `true`/`false` cases for `boolean` discriminants, including when `boolean` is a union variant. - [#​10125](biomejs/biome#10125) [`a55a0b6`](biomejs/biome@a55a0b6) Thanks [@​bmish](https://github.com/bmish)! - Fixed a resolver bug where packages that define a typed entry point through `package.json`'s `main` field but omit `types` were ignored during type-aware resolution. Type-aware rules such as [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) can now inspect imports from those packages. - [#​10117](biomejs/biome#10117) [`895e809`](biomejs/biome@895e809) Thanks [@​denizdogan](https://github.com/denizdogan)! - Added support for the `corner-shape` family of CSS properties and the `superellipse()`/`squircle()` value functions, so [`noUnknownProperty`](https://biomejs.dev/linter/rules/no-unknown-property/) and [`noUnknownFunction`](https://biomejs.dev/linter/rules/no-unknown-function/) no longer flag them as unknown. New known properties: `corner-shape`, `corner-block-end-shape`, `corner-block-start-shape`, `corner-bottom-left-shape`, `corner-bottom-right-shape`, `corner-bottom-shape`, `corner-end-end-shape`, `corner-end-start-shape`, `corner-inline-end-shape`, `corner-inline-start-shape`, `corner-left-shape`, `corner-right-shape`, `corner-start-end-shape`, `corner-start-start-shape`, `corner-top-left-shape`, `corner-top-right-shape`, `corner-top-shape`. New known value functions: `superellipse()`, `squircle()`. - [#​8620](biomejs/biome#8620) [`8df8f73`](biomejs/biome@8df8f73) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​8062](biomejs/biome#8062): Added support for parsing Vue `v-for` directives more accurately. - [#​10191](biomejs/biome#10191) [`aa055cd`](biomejs/biome@aa055cd) Thanks [@​guney](https://github.com/guney)! - Now the rule [`noStaticElementInteractions`](https://biomejs.dev/linter/rules/no-static-element-interactions/) doesn't trigger custom elements. - [#​9757](biomejs/biome#9757) [`2c62594`](biomejs/biome@2c62594) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​9099](biomejs/biome#9099): the HTML formatter collapsing non-text children (inline elements, Svelte expressions, comments) onto a single line when the source had them on separate lines. Biome now preserves the user's intended line breaks for exclusively non-text children. For example, the following Svelte snippet is now preserved instead of being collapsed to `<div>{name}<!-- comment --></div>`: ```svelte <div> {name}<!-- comment --> </div> ``` Similarly, HTML elements like `<span>` inside a `<div>` are now preserved when written on their own line: ```html <div> <span>text</span> </div> ``` - [#​10105](biomejs/biome#10105) [`e7c1a6d`](biomejs/biome@e7c1a6d) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​10039](biomejs/biome#10039): [`useReadonlyClassProperties`](https://biomejs.dev/linter/rules/use-readonly-class-properties/) now detects unreassigned private members in class expressions and export default classes, not only in class declarations. The following patterns are now correctly flagged: ```ts const AnonClass = class { #prop = 123; constructor() { console.log(this.#prop); } }; export default class { #prop = 123; constructor() { console.log(this.#prop); } } ``` - [#​10141](biomejs/biome#10141) [`46a77d0`](biomejs/biome@46a77d0) Thanks [@​minseong0324](https://github.com/minseong0324)! - Improved [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/) to detect conditions that are always truthy because they check built-in global class instances such as `Date`, `Map`, `Set`, `WeakMap`, and `Error`. - [#​10178](biomejs/biome#10178) [`7b05a89`](biomejs/biome@7b05a89) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10177](biomejs/biome#10177): The HTML parser no longer reports lowercase `html` or `doctype` text as invalid after void elements such as `<br>`. - [#​10155](biomejs/biome#10155) [`0d4595d`](biomejs/biome@0d4595d) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​10045](biomejs/biome#10045): the CSS formatter no longer compounds indentation inside nested functional pseudo-classes such as `:not(:where(...))`, `:is(:where(...))`, and similar combinations. The same fix also removes one level of unnecessary indentation that was added inside any pseudo-class function whose argument list wrapped onto multiple lines, including `:nth-child(... of ...)`, `::part(...)`, and `:active-view-transition-type(...)`. The following snippet is now correctly formatted, matching Prettier. ```css input:not( :where( [type="submit"], [type="checkbox"], [type="radio"], [type="button"], [type="reset"] ) ) { inline-size: 100%; } ``` - [#​10112](biomejs/biome#10112) [`6f0251e`](biomejs/biome@6f0251e) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10110](biomejs/biome#10110): Biome's parser now accepts surrogate code points in JavaScript string `\u{...}` escapes. - [#​10141](biomejs/biome#10141) [`46a77d0`](biomejs/biome@46a77d0) Thanks [@​minseong0324](https://github.com/minseong0324)! - Improved [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) to detect `object` return annotations that hide built-in global class instances such as `Date`, `Map`, `Set`, `WeakMap`, and `Error`. - [#​10083](biomejs/biome#10083) [`4a664c1`](biomejs/biome@4a664c1) Thanks [@​ematipico](https://github.com/ematipico)! - Added two new options to [`noShadow`](https://biomejs.dev/linter/rules/no-shadow/), both defaulting to `true` to match typescript-eslint's behavior. Fixed [#​9482](biomejs/biome#9482): Added `ignoreFunctionTypeParameterNameValueShadow` option. When enabled, parameter names inside function type annotations (e.g. `(options: unknown) => void`) are not flagged as shadowing outer variables. Fixed [#​7812](biomejs/biome#7812): Added `ignoreTypeValueShadow` option. When enabled, a value binding that shares its name with a type-only declaration (type alias or interface) is not flagged, since types and values occupy separate namespaces in TypeScript. - [#​9286](biomejs/biome#9286) [`52695cf`](biomejs/biome@52695cf) Thanks [@​Hugo-Polloli](https://github.com/Hugo-Polloli)! - Fixed [#​6316](biomejs/biome#6316): Biome now resolves Svelte `$store` references to the underlying `store` binding in semantic analysis, preventing false `noUndeclaredVariables` diagnostics when the store is declared. - [#​10188](biomejs/biome#10188) [`ae659dd`](biomejs/biome@ae659dd) Thanks [@​dyc3](https://github.com/dyc3)! - Added a new nursery rule [`noExcessiveNestedCallbacks`](https://biomejs.dev/linter/rules/no-excessive-nested-callbacks/), which disallows callbacks nested deeper than the configured maximum. - [#​9757](biomejs/biome#9757) [`2c62594`](biomejs/biome@2c62594) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​9450](biomejs/biome#9450): the HTML formatter now correctly preserves multiline formatting for nested `<template>` elements (e.g. `<template #body>`) when the source has children on separate lines. Previously, the children were collapsed onto a single line. ```diff <template> <UModal> - <template #body> <p>content</p> </template> + <template #body> + <p>content</p> + </template> </UModal> </template> ``` - [#​10118](biomejs/biome#10118) [`c6edcb4`](biomejs/biome@c6edcb4) Thanks [@​Netail](https://github.com/Netail)! - Fixed [#​10024](biomejs/biome#10024): `biome migrate eslint` correctly migrates `eslint` rules that belong to multiple Biome rules. </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:eyJjcmVhdGVkSW5WZXIiOiI0My4xNjAuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE2MC4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://git.oirnoir.dev/OIRNOIR/YouTube-Helper-Server/pulls/10
Claude Code assist writing code. I decided all about it.
Summary
Fixes #10039.
The
SemanticClassservice visitor matched onlyJsClassDeclaration, so class expressions and export default classes were silently skipped. Widen both the visitor and the rule's query toAnyJsClass, which already exposes the only method the rule needs (members).Test Plan
New fixture
invalid_classExpression.tscovers the three forms the rule was missing:const X = class { #prop = ... }(anonymous class expression — theissue's direct reproduction)
const X = class Named { ... }(named class expression)export default class { ... }(anonymous export default class)Docs