fix(lint): noMisleadingReturnType false positive on union with exhausted boolean#10115
Conversation
🦋 Changeset detectedLatest commit: b0f1701 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 |
d5f2062 to
d83b461
Compare
Merging this PR will not alter performance
Comparing Footnotes
|
d83b461 to
6a96f2e
Compare
c5bd9f4 to
5c601d6
Compare
baff7f5 to
fe7d926
Compare
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThis PR adds boolean union canonicalisation across the type system and introduces a predefined Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 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.
🧹 Nitpick comments (4)
.changeset/calm-rivers-flow.md (1)
5-5: Reference the tracked issue in the bug-fix line.Per the changeset guideline, bug-fix entries should start with
Fixed [#NUMBER](issue link): ...when a GitHub issue exists. Issue#9810is referenced by this PR, so let's link it.📝 Suggested wording
-[`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. +Fixed [`#9810`](https://github.com/biomejs/biome/issues/9810): [`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.As per coding guidelines: "For changeset descriptions of bug fixes, reference the issue with a link (e.g., 'Fixed
#4444')".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.changeset/calm-rivers-flow.md at line 5, Update the changeset entry for the bug fix so the description starts with the required "Fixed [`#9810`](https://github.com/your-repo/issues/9810):" prefix; specifically edit the .changeset/calm-rivers-flow.md line that mentions the noMisleadingReturnType rule and replace the current sentence with one beginning "Fixed [`#9810`](https://github.com/your-repo/issues/9810): noMisleadingReturnType no longer reports false positives when a union return type's `boolean` variant is covered by both `true` and `false` returns." Ensure the issue number and URL are correct and keep the rest of the text unchanged.crates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rs (1)
602-602: Tiny doc nit. The comment links[TypeData::union_of]— double-check the intra-doc link resolves (i.e.union_ofispubonTypeData), otherwisecargo docwill warn.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rs` at line 602, The doc comment references TypeData::union_of but may produce a broken intra-doc link; verify that the method/associated function union_of on TypeData is exported (pub) and that the path matches the actual symbol name, and if it is not public either make union_of pub or update the comment to point to the correct public item (or use plain text) so the intra-doc link resolves without cargo doc warnings; check the TypeData type and the union_of item name to ensure the link syntax [`TypeData::union_of`] is correct.crates/biome_js_type_info/src/type.rs (1)
92-116: Same algorithm, second copy.This mirrors
normalize_boolean_union_variantsincrates/biome_js_type_info/src/helpers.rs, just at theTypelevel instead ofTypeReference. Functionally fine, but keeping the two implementations in lock-step is on us forever — worth a follow-up to extract the shared classification (has_boolean / has_true / has_false → action) so a future tweak only has to land in one place.Also: the
templatedance is only needed to inherit a resolver forwith_id. If you exposed something likeType::from_id(self.resolver.clone(), GLOBAL_BOOLEAN_ID)at this call site, you could skip thefind(...).cloned()step entirely.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_type_info/src/type.rs` around lines 92 - 116, Extract the duplicated boolean-union classification logic (has_boolean / has_true / has_false → action) from normalized_boolean_union_variants in Type (and the existing normalize_boolean_union_variants in helpers.rs) into a shared helper function used by both Type and TypeReference so future changes land in one place; additionally add a constructor/associated fn on Type (e.g. Type::from_id taking a resolver and GLOBAL_BOOLEAN_ID) so normalized_boolean_union_variants can construct the boolean Type directly instead of doing the current template find().cloned() + with_id dance, then update normalized_boolean_union_variants to call the shared classifier and use Type::from_id(GLOBAL_BOOLEAN_ID) (or equivalent) when injecting the boolean variant.crates/biome_js_type_info/src/helpers.rs (1)
327-353: Logic is correct, a couple of small polish opportunities.
!(has_boolean || has_true && has_false)parses as!(has_boolean || (has_true && has_false))thanks to&&binding tighter than||. Adding parens would save the next reader a trip to the precedence table.- Each
any(...)re-callsresolver.resolve_and_get(ty)— a single pass classifying every variant once would do the same job with one resolution per entry.- This is conceptually the same algorithm as
Type::normalized_boolean_union_variantsintype.rs. Worth a TODO to share a single source of truth eventually.♻️ Suggested clarity tweak
- if !(has_boolean || has_true && has_false) { + if !(has_boolean || (has_true && has_false)) { return; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_type_info/src/helpers.rs` around lines 327 - 353, In normalize_boolean_union_variants: add parentheses around the conditional check to make the intent explicit (e.g. !(has_boolean || (has_true && has_false))); then refactor the logic to do a single pass over variants calling resolver.resolve_and_get once per entry to classify each variant into boolean keyword / true literal / false literal (use is_boolean_keyword_reference and is_boolean_literal_reference semantics) while building a new retained list without boolean literals; after the pass, set has_boolean/has_true/has_false from those flags, replace variants with the retained list, and if !has_boolean but has_true && has_false push TypeReference::Resolved(GLOBAL_BOOLEAN_ID); add a TODO note referencing Type::normalized_boolean_union_variants in type.rs for future sharing of logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In @.changeset/calm-rivers-flow.md:
- Line 5: Update the changeset entry for the bug fix so the description starts
with the required "Fixed [`#9810`](https://github.com/your-repo/issues/9810):"
prefix; specifically edit the .changeset/calm-rivers-flow.md line that mentions
the noMisleadingReturnType rule and replace the current sentence with one
beginning "Fixed [`#9810`](https://github.com/your-repo/issues/9810):
noMisleadingReturnType no longer reports false positives when a union return
type's `boolean` variant is covered by both `true` and `false` returns." Ensure
the issue number and URL are correct and keep the rest of the text unchanged.
In `@crates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rs`:
- Line 602: The doc comment references TypeData::union_of but may produce a
broken intra-doc link; verify that the method/associated function union_of on
TypeData is exported (pub) and that the path matches the actual symbol name, and
if it is not public either make union_of pub or update the comment to point to
the correct public item (or use plain text) so the intra-doc link resolves
without cargo doc warnings; check the TypeData type and the union_of item name
to ensure the link syntax [`TypeData::union_of`] is correct.
In `@crates/biome_js_type_info/src/helpers.rs`:
- Around line 327-353: In normalize_boolean_union_variants: add parentheses
around the conditional check to make the intent explicit (e.g. !(has_boolean ||
(has_true && has_false))); then refactor the logic to do a single pass over
variants calling resolver.resolve_and_get once per entry to classify each
variant into boolean keyword / true literal / false literal (use
is_boolean_keyword_reference and is_boolean_literal_reference semantics) while
building a new retained list without boolean literals; after the pass, set
has_boolean/has_true/has_false from those flags, replace variants with the
retained list, and if !has_boolean but has_true && has_false push
TypeReference::Resolved(GLOBAL_BOOLEAN_ID); add a TODO note referencing
Type::normalized_boolean_union_variants in type.rs for future sharing of logic.
In `@crates/biome_js_type_info/src/type.rs`:
- Around line 92-116: Extract the duplicated boolean-union classification logic
(has_boolean / has_true / has_false → action) from
normalized_boolean_union_variants in Type (and the existing
normalize_boolean_union_variants in helpers.rs) into a shared helper function
used by both Type and TypeReference so future changes land in one place;
additionally add a constructor/associated fn on Type (e.g. Type::from_id taking
a resolver and GLOBAL_BOOLEAN_ID) so normalized_boolean_union_variants can
construct the boolean Type directly instead of doing the current template
find().cloned() + with_id dance, then update normalized_boolean_union_variants
to call the shared classifier and use Type::from_id(GLOBAL_BOOLEAN_ID) (or
equivalent) when injecting the boolean variant.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 080d561a-1fce-416d-a908-1897f4519c08
⛔ Files ignored due to path filters (9)
crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/invalid.ts.snapis excluded by!**/*.snapand included by**crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/valid.ts.snapis excluded by!**/*.snapand included by**crates/biome_js_analyze/tests/specs/nursery/useExhaustiveSwitchCases/invalid.ts.snapis excluded by!**/*.snapand included by**crates/biome_js_type_info/tests/snapshots/infer_type_of_function_with_destructured_arguments.snapis excluded by!**/*.snapand included by**crates/biome_module_graph/tests/snapshots/test_resolve_export_type_referencing_imported_type.snapis excluded by!**/*.snapand included by**crates/biome_module_graph/tests/snapshots/test_resolve_exports.snapis excluded by!**/*.snapand included by**crates/biome_module_graph/tests/snapshots/test_resolve_promise_from_imported_function_returning_imported_promise_type.snapis excluded by!**/*.snapand included by**crates/biome_module_graph/tests/snapshots/test_resolve_promise_from_imported_function_returning_reexported_promise_type.snapis excluded by!**/*.snapand included by**crates/biome_module_graph/tests/snapshots/test_resolve_type_of_property_with_getter.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (12)
.changeset/calm-rivers-flow.mdcrates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rscrates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rscrates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/invalid.tscrates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/valid.tscrates/biome_js_analyze/tests/specs/nursery/useExhaustiveSwitchCases/invalid.tscrates/biome_js_type_info/src/globals.rscrates/biome_js_type_info/src/globals_ids.rscrates/biome_js_type_info/src/helpers.rscrates/biome_js_type_info/src/lib.rscrates/biome_js_type_info/src/type.rscrates/biome_js_type_info/tests/flattening.rs
04a3452 to
36da022
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (5)
crates/biome_js_type_info/src/helpers.rs (2)
327-378: Note the parallel implementation intype.rs.
Type::normalized_boolean_union_variants(incrates/biome_js_type_info/src/type.rs) implements the exact same canonicalisation rule on aVec<Type>instead ofVec<TypeReference>. Two sources of truth for the same invariant is a minor maintenance hazard — if one is later tweaked (e.g. to also collapseboolean | true | falsedifferently), the other will silently drift. Worth a short doc comment cross-referencing them so future maintainers know to keep them in sync, or extracting the shared "(has_boolean, has_true, has_false) → action" decision into a tiny helper. Not a blocker.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_type_info/src/helpers.rs` around lines 327 - 378, The boolean-union canonicalization in normalize_boolean_union_variants duplicates the logic in Type::normalized_boolean_union_variants; either add a short doc comment on normalize_boolean_union_variants that cross-references Type::normalized_boolean_union_variants (and vice‑versa) so maintainers know they must stay in sync, or refactor the shared decision logic (the has_boolean/has_true/has_false detection and resulting action) into a tiny shared helper used by both normalize_boolean_union_variants and Type::normalized_boolean_union_variants to avoid two sources of truth.
330-356: Optional: collapse the three scans into one.
has_boolean,has_true, andhas_falseeach iteratevariantsand resolve every reference independently — three resolver lookups per element before we even get toretain. A single pass would be cheaper and arguably clearer. Logic-wise the current code is correct (operator precedence in the early-return condition is fine).♻️ Suggested single-pass variant
- let has_boolean = variants - .iter() - .any(|ty| is_boolean_keyword_reference(resolver, ty)); - let has_true = variants - .iter() - .any(|ty| is_boolean_literal_reference(resolver, ty, true)); - let has_false = variants - .iter() - .any(|ty| is_boolean_literal_reference(resolver, ty, false)); + let (mut has_boolean, mut has_true, mut has_false) = (false, false, false); + for ty in variants.iter() { + match resolver.resolve_and_get(ty).as_ref().map(|r| r.as_raw_data()) { + Some(TypeData::Boolean) => has_boolean = true, + Some(TypeData::Literal(lit)) => match lit.as_ref() { + Literal::Boolean(b) if b.as_bool() => has_true = true, + Literal::Boolean(_) => has_false = true, + _ => {} + }, + _ => {} + } + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_type_info/src/helpers.rs` around lines 330 - 356, The three separate scans in normalize_boolean_union_variants are inefficient; replace them with a single pass over variants that checks each TypeReference once using is_boolean_keyword_reference and is_boolean_literal_reference to set has_boolean, has_true, and has_false flags (and optionally mark which indexes are literal true/false). After the single pass, use the same early-return logic (if !(has_boolean || (has_true && has_false)) return), then remove boolean literal references (e.g., via variants.retain or by constructing a filtered Vec) and, if has_boolean is false, push TypeReference::Resolved(GLOBAL_BOOLEAN_ID); keep the function name and calls to is_boolean_keyword_reference, is_boolean_literal_reference, and GLOBAL_BOOLEAN_ID unchanged.crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/valid.ts (1)
161-174: Solid valid-case set; one nit on placement.The five new cases — including
duplicateBooleanReturnsto verify dedup before canonicalisation — give good coverage. Minor nit: they're inserted betweenstoreObj(line 159) andStaticStore(line 175), which splits the "getter + setter" cluster. Consider moving the boolean-union block to the end of the file (afterStaticStore) so related groups stay contiguous. Non-blocking.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/valid.ts` around lines 161 - 174, The added boolean-union test cases (useCloudLogin, booleanOrUndefined, booleanOrLiteral, nullOrBoolean, duplicateBooleanReturns) are placed between the related "getter + setter" cluster (storeObj and StaticStore); move this entire block of five functions so it appears after the StaticStore block (i.e., append the boolean-union block to the end of the file after the StaticStore declaration) to keep related test groups contiguous.crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs (1)
254-275: Tiny nit: rename the loop binding.
for ty in &state.missing_casesreads a bit oddly now that the element type isMissingCase, notType. Renaming tocase(matching the helper parameter names below) keeps things consistent.♻️ Suggested rename
- for ty in &state.missing_cases { + for case in &state.missing_cases { @@ - missing_case_to_expression(ty)?, + missing_case_to_expression(case)?,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs` around lines 254 - 275, Rename the loop binding `ty` in the `for ty in &state.missing_cases` loop to `case` (or `missing_case`) to reflect the element type `MissingCase` and match the helper names like `missing_case_to_expression`; update the loop header and all uses of `ty` inside the loop (where you call `missing_case_to_expression(ty)?`, build the `case_token`, construct the `AnyJsSwitchClause::JsCaseClause` via `make::js_case_clause`, and when pushing to `clauses`) so names are consistent and clearer.crates/biome_js_type_info/src/type.rs (1)
87-116: Mirrorshelpers.rs::normalize_boolean_union_variants— cross-link them.This
Type-level helper duplicates the canonicalisation already performed insideTypeData::union_of(viahelpers.rs::normalize_boolean_union_variants). The two will run on different inputs (already-resolvedTypevalues vs rawTypeReferences during union construction), so consolidating fully is awkward, but at minimum a doc-comment cross-reference would help future maintainers keep the rules in sync.Also: the
templatedance is fine, but since you've established thathas_true && has_falseholds in the!has_booleanbranch, thefindis guaranteed to returnSome. A tiny readability win is to express that without theOption<Option<_>>flatten:♻️ Slightly tidier template extraction
- let template = (!has_boolean) - .then(|| { - types - .iter() - .find(|ty| ty.is_boolean_literal(true) || ty.is_boolean_literal(false)) - .cloned() - }) - .flatten(); + let template = (!has_boolean).then(|| { + types + .iter() + .find(|ty| ty.is_boolean_literal(true) || ty.is_boolean_literal(false)) + .cloned() + .expect("has_true && has_false implies a literal variant exists") + });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_type_info/src/type.rs` around lines 87 - 116, Add a doc-comment cross-reference in Type::normalized_boolean_union_variants pointing to helpers.rs::normalize_boolean_union_variants so maintainers know these two routines implement the same canonicalization rules, and simplify the template extraction: replace the current Option<Option> flatten pattern by directly finding and cloning the boolean literal (use find(...).cloned().expect(...) or equivalent) inside the (!has_boolean) branch because has_true && has_false guarantees a match; keep the subsequent retain(...) and push(template.with_id(...)) behavior intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs`:
- Around line 254-275: Rename the loop binding `ty` in the `for ty in
&state.missing_cases` loop to `case` (or `missing_case`) to reflect the element
type `MissingCase` and match the helper names like `missing_case_to_expression`;
update the loop header and all uses of `ty` inside the loop (where you call
`missing_case_to_expression(ty)?`, build the `case_token`, construct the
`AnyJsSwitchClause::JsCaseClause` via `make::js_case_clause`, and when pushing
to `clauses`) so names are consistent and clearer.
In `@crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/valid.ts`:
- Around line 161-174: The added boolean-union test cases (useCloudLogin,
booleanOrUndefined, booleanOrLiteral, nullOrBoolean, duplicateBooleanReturns)
are placed between the related "getter + setter" cluster (storeObj and
StaticStore); move this entire block of five functions so it appears after the
StaticStore block (i.e., append the boolean-union block to the end of the file
after the StaticStore declaration) to keep related test groups contiguous.
In `@crates/biome_js_type_info/src/helpers.rs`:
- Around line 327-378: The boolean-union canonicalization in
normalize_boolean_union_variants duplicates the logic in
Type::normalized_boolean_union_variants; either add a short doc comment on
normalize_boolean_union_variants that cross-references
Type::normalized_boolean_union_variants (and vice‑versa) so maintainers know
they must stay in sync, or refactor the shared decision logic (the
has_boolean/has_true/has_false detection and resulting action) into a tiny
shared helper used by both normalize_boolean_union_variants and
Type::normalized_boolean_union_variants to avoid two sources of truth.
- Around line 330-356: The three separate scans in
normalize_boolean_union_variants are inefficient; replace them with a single
pass over variants that checks each TypeReference once using
is_boolean_keyword_reference and is_boolean_literal_reference to set
has_boolean, has_true, and has_false flags (and optionally mark which indexes
are literal true/false). After the single pass, use the same early-return logic
(if !(has_boolean || (has_true && has_false)) return), then remove boolean
literal references (e.g., via variants.retain or by constructing a filtered Vec)
and, if has_boolean is false, push TypeReference::Resolved(GLOBAL_BOOLEAN_ID);
keep the function name and calls to is_boolean_keyword_reference,
is_boolean_literal_reference, and GLOBAL_BOOLEAN_ID unchanged.
In `@crates/biome_js_type_info/src/type.rs`:
- Around line 87-116: Add a doc-comment cross-reference in
Type::normalized_boolean_union_variants pointing to
helpers.rs::normalize_boolean_union_variants so maintainers know these two
routines implement the same canonicalization rules, and simplify the template
extraction: replace the current Option<Option> flatten pattern by directly
finding and cloning the boolean literal (use find(...).cloned().expect(...) or
equivalent) inside the (!has_boolean) branch because has_true && has_false
guarantees a match; keep the subsequent retain(...) and
push(template.with_id(...)) behavior intact.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: fd14ef3d-01db-4bfa-a3f6-3c282cd6f91a
⛔ Files ignored due to path filters (9)
crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/invalid.ts.snapis excluded by!**/*.snapand included by**crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/valid.ts.snapis excluded by!**/*.snapand included by**crates/biome_js_analyze/tests/specs/nursery/useExhaustiveSwitchCases/invalid.ts.snapis excluded by!**/*.snapand included by**crates/biome_js_type_info/tests/snapshots/infer_type_of_function_with_destructured_arguments.snapis excluded by!**/*.snapand included by**crates/biome_module_graph/tests/snapshots/test_resolve_export_type_referencing_imported_type.snapis excluded by!**/*.snapand included by**crates/biome_module_graph/tests/snapshots/test_resolve_exports.snapis excluded by!**/*.snapand included by**crates/biome_module_graph/tests/snapshots/test_resolve_promise_from_imported_function_returning_imported_promise_type.snapis excluded by!**/*.snapand included by**crates/biome_module_graph/tests/snapshots/test_resolve_promise_from_imported_function_returning_reexported_promise_type.snapis excluded by!**/*.snapand included by**crates/biome_module_graph/tests/snapshots/test_resolve_type_of_property_with_getter.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (12)
.changeset/calm-rivers-flow.mdcrates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rscrates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rscrates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/invalid.tscrates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/valid.tscrates/biome_js_analyze/tests/specs/nursery/useExhaustiveSwitchCases/invalid.tscrates/biome_js_type_info/src/globals.rscrates/biome_js_type_info/src/globals_ids.rscrates/biome_js_type_info/src/helpers.rscrates/biome_js_type_info/src/lib.rscrates/biome_js_type_info/src/type.rscrates/biome_js_type_info/tests/flattening.rs
✅ Files skipped from review due to trivial changes (2)
- crates/biome_js_type_info/src/lib.rs
- .changeset/calm-rivers-flow.md
🚧 Files skipped from review as they are similar to previous changes (4)
- crates/biome_js_type_info/src/globals.rs
- crates/biome_js_type_info/src/globals_ids.rs
- crates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rs
- crates/biome_js_type_info/tests/flattening.rs
36da022 to
8b3b56d
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (5)
crates/biome_js_type_info/src/type.rs (2)
73-85:with_id: nice helper, soft contract worth flagging.The
debug_assert!is great for tests but in release builds an unknown id silently degrades toUNKNOWN_DATAviaDeref. Today the only caller passesGLOBAL_BOOLEAN_ID, which any sane resolver in this codebase resolves, so this is fine. Ifwith_idever becomes public-facing for arbitrary ids, consider returningOption<Self>instead.Also, the doc comment mentions only "predefined global ID" — works for now, but future callers may want a clearer rule.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_type_info/src/type.rs` around lines 73 - 85, The current Type::with_id uses a debug_assert! to check resolver can resolve the provided ResolvedTypeId, which is silent in release builds and can lead to UNKNOWN_DATA; change the API to return Option<Self> (or Result<Self, ...>) instead of Self so callers must handle unknown ids—update the function signature of with_id to return Option<Type>, perform a runtime check using self.resolver.get_by_resolved_id(id).is_some() and return Some(Self { resolver: self.resolver.clone(), id }) or None; update callers (e.g., where GLOBAL_BOOLEAN_ID is used) to unwrap or handle the Option and amend the doc comment to state the contract clearly (that callers must supply a resolver-known ResolvedTypeId or handle None).
94-129: Logic checks out across the four interesting shapes.Walked through
true|false,boolean|true,boolean|true|false, andbooleanalone — all collapse correctly, and theseen_booleanretain dedupes aliasedBooleanreferences to one. 👍Minor:
- Same readability tweak as
helpers.rs:!(has_boolean || (has_true && has_false))parses faster.crate::globals_ids::GLOBAL_BOOLEAN_IDcould just be added to the existinguse crate::globals::{ ... }block (it's re-exported there) to avoid the inline path:use crate::globals::{ - GLOBAL_ARRAY_ID, GLOBAL_ASYNC_DISPOSABLE_ID, GLOBAL_DISPOSABLE_ID, GLOBAL_NUMBER_ID, + GLOBAL_ARRAY_ID, GLOBAL_ASYNC_DISPOSABLE_ID, GLOBAL_BOOLEAN_ID, GLOBAL_DISPOSABLE_ID, GLOBAL_NUMBER_ID, GLOBAL_PROMISE_ID, GLOBAL_STRING_ID, GLOBAL_SYMBOL_ASYNC_DISPOSE_ID, GLOBAL_SYMBOL_DISPOSE_ID, GLOBAL_UNKNOWN_ID, },- types.push(template.with_id(crate::globals_ids::GLOBAL_BOOLEAN_ID)); + types.push(template.with_id(GLOBAL_BOOLEAN_ID));🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_type_info/src/type.rs` around lines 94 - 129, The function normalized_boolean_union_variants is fine but please apply two small readability tweaks: (1) change the conditional !(has_boolean || has_true && has_false) to the clearer form !(has_boolean || (has_true && has_false)) around the early-return so the precedence is explicit, and (2) replace the inline path crate::globals_ids::GLOBAL_BOOLEAN_ID by importing GLOBAL_BOOLEAN_ID from the crate::globals re-export (add GLOBAL_BOOLEAN_ID to the existing use crate::globals::{ ... } block) and then use GLOBAL_BOOLEAN_ID in the types.push call.crates/biome_js_type_info/src/helpers.rs (2)
327-378: Heads-up: this duplicatesType::normalized_boolean_union_variantsintype.rs.Same algorithm, different value type (
TypeReferencevsType). Not a blocker — they operate at different layers — but if it ever drifts, the lints will silently diverge fromunion_of. Worth a small shared primitive (e.g. a generic helper takingis_boolean/is_literal/make_booleanclosures) at some point.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_type_info/src/helpers.rs` around lines 327 - 378, The logic in normalize_boolean_union_variants (helpers.rs) duplicates Type::normalized_boolean_union_variants (type.rs); extract the shared algorithm into a single generic helper that both layers call by parameterizing the type-specific checks/constructors via closures (e.g., take is_boolean_predicate, is_literal_predicate, and make_boolean_constructor closures) and then replace normalize_boolean_union_variants and Type::normalized_boolean_union_variants to invoke that helper; reference the existing helpers is_boolean_literal_reference and is_boolean_keyword_reference as the predicates to wire into the new generic function so both implementations reuse the same canonicalization logic.
327-378: Logic is correct; readability nit on the early-return condition.The four-case truth table checks out (
booleanalone,true|false,boolean|true, neither). Two small suggestions:
!(has_boolean || has_true && has_false)relies on&&binding tighter than||. It's correct but a quick parenthesis makes it scan instantly:- if !(has_boolean || has_true && has_false) { + if !(has_boolean || (has_true && has_false)) { return; }
- Three full passes of
iter().any(...)overvariantsbefore theretaincould fold into one loop. Not a hot path today, so feel free to defer.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_type_info/src/helpers.rs` around lines 327 - 378, In normalize_boolean_union_variants the early-return condition is correct but ambiguous; change the if condition to use explicit parentheses (e.g., if !(has_boolean || (has_true && has_false)) ) for clarity. Optionally, to avoid three separate iter().any passes, replace the three .any calls with a single loop over variants that sets has_boolean, has_true and has_false flags (still using is_boolean_keyword_reference and is_boolean_literal_reference) before the early return and retain logic.crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs (1)
158-163: Nit:matchon aboolreads a bit awkwardly.A plain
if/elseis more idiomatic here (and Clippy tends to grumble aboutmatch true => … false => …). Same applies to lines 330–333 and the inner pattern at 343–346, if you want to harmonise them.♻️ Suggested tweak
- let variants = match discriminant_ty.is_union() { - true => Type::normalized_boolean_union_variants( - discriminant_ty.flattened_union_variants().collect(), - ), - false => vec![discriminant_ty], - }; + let variants = if discriminant_ty.is_union() { + Type::normalized_boolean_union_variants( + discriminant_ty.flattened_union_variants().collect(), + ) + } else { + vec![discriminant_ty] + };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs` around lines 158 - 163, The current code uses match on a boolean to set variants (matching discriminant_ty.is_union()), which is awkward; replace the match expression that assigns variants with an idiomatic if/else using discriminant_ty.is_union() to choose between Type::normalized_boolean_union_variants(...) and vec![discriminant_ty]; apply the same refactor to the other occurrences mentioned (the block using discriminant_ty.is_union() at the locations corresponding to lines ~330–333 and the inner pattern around ~343–346) so all boolean matches become simple if/else branches referencing the same expressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs`:
- Around line 158-163: The current code uses match on a boolean to set variants
(matching discriminant_ty.is_union()), which is awkward; replace the match
expression that assigns variants with an idiomatic if/else using
discriminant_ty.is_union() to choose between
Type::normalized_boolean_union_variants(...) and vec![discriminant_ty]; apply
the same refactor to the other occurrences mentioned (the block using
discriminant_ty.is_union() at the locations corresponding to lines ~330–333 and
the inner pattern around ~343–346) so all boolean matches become simple if/else
branches referencing the same expressions.
In `@crates/biome_js_type_info/src/helpers.rs`:
- Around line 327-378: The logic in normalize_boolean_union_variants
(helpers.rs) duplicates Type::normalized_boolean_union_variants (type.rs);
extract the shared algorithm into a single generic helper that both layers call
by parameterizing the type-specific checks/constructors via closures (e.g., take
is_boolean_predicate, is_literal_predicate, and make_boolean_constructor
closures) and then replace normalize_boolean_union_variants and
Type::normalized_boolean_union_variants to invoke that helper; reference the
existing helpers is_boolean_literal_reference and is_boolean_keyword_reference
as the predicates to wire into the new generic function so both implementations
reuse the same canonicalization logic.
- Around line 327-378: In normalize_boolean_union_variants the early-return
condition is correct but ambiguous; change the if condition to use explicit
parentheses (e.g., if !(has_boolean || (has_true && has_false)) ) for clarity.
Optionally, to avoid three separate iter().any passes, replace the three .any
calls with a single loop over variants that sets has_boolean, has_true and
has_false flags (still using is_boolean_keyword_reference and
is_boolean_literal_reference) before the early return and retain logic.
In `@crates/biome_js_type_info/src/type.rs`:
- Around line 73-85: The current Type::with_id uses a debug_assert! to check
resolver can resolve the provided ResolvedTypeId, which is silent in release
builds and can lead to UNKNOWN_DATA; change the API to return Option<Self> (or
Result<Self, ...>) instead of Self so callers must handle unknown ids—update the
function signature of with_id to return Option<Type>, perform a runtime check
using self.resolver.get_by_resolved_id(id).is_some() and return Some(Self {
resolver: self.resolver.clone(), id }) or None; update callers (e.g., where
GLOBAL_BOOLEAN_ID is used) to unwrap or handle the Option and amend the doc
comment to state the contract clearly (that callers must supply a resolver-known
ResolvedTypeId or handle None).
- Around line 94-129: The function normalized_boolean_union_variants is fine but
please apply two small readability tweaks: (1) change the conditional
!(has_boolean || has_true && has_false) to the clearer form !(has_boolean ||
(has_true && has_false)) around the early-return so the precedence is explicit,
and (2) replace the inline path crate::globals_ids::GLOBAL_BOOLEAN_ID by
importing GLOBAL_BOOLEAN_ID from the crate::globals re-export (add
GLOBAL_BOOLEAN_ID to the existing use crate::globals::{ ... } block) and then
use GLOBAL_BOOLEAN_ID in the types.push call.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f50c83b5-0fac-468f-a0ba-dc439e8283ea
⛔ Files ignored due to path filters (9)
crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/invalid.ts.snapis excluded by!**/*.snapand included by**crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/valid.ts.snapis excluded by!**/*.snapand included by**crates/biome_js_analyze/tests/specs/nursery/useExhaustiveSwitchCases/invalid.ts.snapis excluded by!**/*.snapand included by**crates/biome_js_type_info/tests/snapshots/infer_type_of_function_with_destructured_arguments.snapis excluded by!**/*.snapand included by**crates/biome_module_graph/tests/snapshots/test_resolve_export_type_referencing_imported_type.snapis excluded by!**/*.snapand included by**crates/biome_module_graph/tests/snapshots/test_resolve_exports.snapis excluded by!**/*.snapand included by**crates/biome_module_graph/tests/snapshots/test_resolve_promise_from_imported_function_returning_imported_promise_type.snapis excluded by!**/*.snapand included by**crates/biome_module_graph/tests/snapshots/test_resolve_promise_from_imported_function_returning_reexported_promise_type.snapis excluded by!**/*.snapand included by**crates/biome_module_graph/tests/snapshots/test_resolve_type_of_property_with_getter.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (12)
.changeset/calm-rivers-flow.mdcrates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rscrates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rscrates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/invalid.tscrates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/valid.tscrates/biome_js_analyze/tests/specs/nursery/useExhaustiveSwitchCases/invalid.tscrates/biome_js_type_info/src/globals.rscrates/biome_js_type_info/src/globals_ids.rscrates/biome_js_type_info/src/helpers.rscrates/biome_js_type_info/src/lib.rscrates/biome_js_type_info/src/type.rscrates/biome_js_type_info/tests/flattening.rs
✅ Files skipped from review due to trivial changes (1)
- .changeset/calm-rivers-flow.md
🚧 Files skipped from review as they are similar to previous changes (2)
- crates/biome_js_type_info/src/lib.rs
- crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/invalid.ts
There was a problem hiding this comment.
🧹 Nitpick comments (3)
crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs (3)
160-165: Tiny nit:matchon a bool reads asif/else.
match discriminant_ty.is_union() { true => ..., false => ... }is the patternclippy::match_boollints against. Anif/elseis a touch friendlier here, but feel free to ignore.♻️ Optional cleanup
- let variants = match discriminant_ty.is_union() { - true => Type::normalized_boolean_union_variants( - discriminant_ty.flattened_union_variants().collect(), - ), - false => vec![discriminant_ty], - }; + let variants = if discriminant_ty.is_union() { + Type::normalized_boolean_union_variants( + discriminant_ty.flattened_union_variants().collect(), + ) + } else { + vec![discriminant_ty] + };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs` around lines 160 - 165, The match on a boolean here is clearer as an if/else: replace the match on discriminant_ty.is_union() that sets variants with an if discriminant_ty.is_union() { /* call Type::normalized_boolean_union_variants with discriminant_ty.flattened_union_variants().collect() */ } else { vec![discriminant_ty] }; keep the same calls to Type::normalized_boolean_union_variants and discriminant_ty.flattened_union_variants() so only the control structure for computing variants (the variable named variants) is changed from match to an if/else.
260-281: Variable name nit:tyno longer holds aType.Now that
state: &Vec<MissingCase>, calling the loop variabletyis a small leftover from the old shape. Renaming tocase(ormissing) matches the new type and the surroundingmissing_case_to_expressioncall.- for ty in state { + for case in state { ... - missing_case_to_expression(ty)?, + missing_case_to_expression(case)?,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs` around lines 260 - 281, Loop variable `ty` no longer represents a Type; rename it to something like `case` or `missing` in the for loop that iterates over `state: &Vec<MissingCase>` and update all usages inside that loop (including the call to `missing_case_to_expression(ty)?` and any references when building `case_token` and `clause`) to the new name so the identifier matches the `MissingCase` semantics.
307-312: Simplify usingis_some_and.The
.and_then(|literal| Some(literal.value_token().ok()?.kind() == T![true]))is harder to read than necessary — you're opening aSome(...)just to use?inside it. Since the project targets Rust 1.94.1,is_some_and(stable since 1.70.0) makes this much cleaner:♻️ Suggested refactor
fn is_true_literal_expression(expr: &AnyJsExpression) -> bool { expr.as_any_js_literal_expression() .and_then(|literal| literal.as_js_boolean_literal_expression()) - .and_then(|literal| Some(literal.value_token().ok()?.kind() == T![true])) - .unwrap_or_default() + .and_then(|literal| literal.value_token().ok()) + .is_some_and(|token| token.kind() == T![true]) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs` around lines 307 - 312, The helper is_true_literal_expression has an unnecessary and_then wrapping a Some(...) to use `?`; replace the third combinator with `is_some_and` to directly test the boolean literal token kind. Specifically, in is_true_literal_expression change the chain that calls as_js_boolean_literal_expression() and then the and_then(|literal| Some(literal.value_token().ok()?.kind() == T![true])) to use is_some_and(|literal| literal.value_token().ok().map(|t| t.kind() == T![true]).unwrap_or(false)) or preferably is_some_and(|literal| literal.value_token().ok().map(|t| t.kind() == T![true]).unwrap_or_default()) so the result is a simple boolean without creating an inner Some.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs`:
- Around line 160-165: The match on a boolean here is clearer as an if/else:
replace the match on discriminant_ty.is_union() that sets variants with an if
discriminant_ty.is_union() { /* call Type::normalized_boolean_union_variants
with discriminant_ty.flattened_union_variants().collect() */ } else {
vec![discriminant_ty] }; keep the same calls to
Type::normalized_boolean_union_variants and
discriminant_ty.flattened_union_variants() so only the control structure for
computing variants (the variable named variants) is changed from match to an
if/else.
- Around line 260-281: Loop variable `ty` no longer represents a Type; rename it
to something like `case` or `missing` in the for loop that iterates over `state:
&Vec<MissingCase>` and update all usages inside that loop (including the call to
`missing_case_to_expression(ty)?` and any references when building `case_token`
and `clause`) to the new name so the identifier matches the `MissingCase`
semantics.
- Around line 307-312: The helper is_true_literal_expression has an unnecessary
and_then wrapping a Some(...) to use `?`; replace the third combinator with
`is_some_and` to directly test the boolean literal token kind. Specifically, in
is_true_literal_expression change the chain that calls
as_js_boolean_literal_expression() and then the and_then(|literal|
Some(literal.value_token().ok()?.kind() == T![true])) to use
is_some_and(|literal| literal.value_token().ok().map(|t| t.kind() ==
T![true]).unwrap_or(false)) or preferably is_some_and(|literal|
literal.value_token().ok().map(|t| t.kind() == T![true]).unwrap_or_default()) so
the result is a simple boolean without creating an inner Some.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 16d6f501-fd1c-441d-a10f-c8c1f193917e
⛔ Files ignored due to path filters (1)
crates/biome_js_analyze/tests/specs/nursery/useExhaustiveSwitchCases/valid.ts.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (4)
.changeset/eleven-impalas-smell.md.changeset/light-wasps-jog.mdcrates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rscrates/biome_js_analyze/tests/specs/nursery/useExhaustiveSwitchCases/valid.ts
✅ Files skipped from review due to trivial changes (2)
- .changeset/eleven-impalas-smell.md
- .changeset/light-wasps-jog.md
34ea360 to
08bdb2c
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (4)
crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs (4)
107-110: Consider movingMissingCasebelow theimpl Ruleblock.Per project convention, helper structs/enums belong below the rule's
implblock. The documented exception is for node unions used in the rule'sQuerytype, butMissingCaseis theStatetype, so it doesn't qualify.Based on learnings from PR 8960: "all helper functions, structs, and enums must be placed below the
impl Ruleblock. The only exception is when declaring a node union to use in the rule's Query type".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs` around lines 107 - 110, The enum MissingCase (used as the rule's State) should be moved below the impl Rule block to follow project convention for helper types; locate the MissingCase declaration and cut/paste it so it appears after the impl Rule { ... } implementation (not before), ensuring any references to MissingCase in the rule's State/Query remain unchanged and compile.
159-164: Preferif/elseovermatchon abool.Slightly more idiomatic and saves a level of indentation:
♻️ Suggested tweak
- let variants = match discriminant_ty.is_union() { - true => Type::normalized_boolean_union_variants( - discriminant_ty.flattened_union_variants().collect(), - ), - false => vec![discriminant_ty], - }; + let variants = if discriminant_ty.is_union() { + Type::normalized_boolean_union_variants( + discriminant_ty.flattened_union_variants().collect(), + ) + } else { + vec![discriminant_ty] + };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs` around lines 159 - 164, Replace the match on the boolean returned by discriminant_ty.is_union() with an if/else for clarity and to remove an unnecessary match; specifically, in the block that defines variants (currently using match discriminant_ty.is_union()), use if discriminant_ty.is_union() { Type::normalized_boolean_union_variants(discriminant_ty.flattened_union_variants().collect()) } else { vec![discriminant_ty] } so the logic around discriminant_ty, normalized_boolean_union_variants, and flattened_union_variants remains the same but uses an idiomatic if/else.
259-280: Rename loop bindingty→case(ormissing).
stateis nowVec<MissingCase>, sotyis a touch misleading at the action site. Cosmetic only.♻️ Suggested tweak
- for ty in state { + for case in state { @@ - missing_case_to_expression(ty)?, + missing_case_to_expression(case)?,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs` around lines 259 - 280, The loop variable name `ty` is misleading because `state` is a Vec<MissingCase>; rename the binding to `case` (or `missing`) in the for loop and update all uses inside the block — e.g., change `for ty in state {` to `for case in state {` and replace `missing_case_to_expression(ty)?` with `missing_case_to_expression(case)?` (also update any other occurrences of `ty` inside this block such as in the `clause` construction that references `throw_stmt`/`clauses`), keeping the same logic and types.
166-188: Stale variable name:intersection_partis now a union variant.Since the loop iterates over union variants (post
normalized_boolean_union_variants),variantwould read more truthfully thanintersection_part. Purely cosmetic.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs` around lines 166 - 188, The loop variable name intersection_part is misleading now that it iterates union variants; rename the loop variable to variant and update all uses accordingly (e.g., change for intersection_part in variants to for variant in variants, then call flatten_type(&variant) and update subsequent checks and contains calls to use the new name or a clearly named flattened variable such as flat_variant), ensuring references to has_boolean_case, missing_cases.push(MissingCase::BooleanLiteral(...)), found_cases.contains(...), and missing_cases.push(MissingCase::Type(...)) use the updated identifier names so the code remains correct and readable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rs`:
- Around line 107-110: The enum MissingCase (used as the rule's State) should be
moved below the impl Rule block to follow project convention for helper types;
locate the MissingCase declaration and cut/paste it so it appears after the impl
Rule { ... } implementation (not before), ensuring any references to MissingCase
in the rule's State/Query remain unchanged and compile.
- Around line 159-164: Replace the match on the boolean returned by
discriminant_ty.is_union() with an if/else for clarity and to remove an
unnecessary match; specifically, in the block that defines variants (currently
using match discriminant_ty.is_union()), use if discriminant_ty.is_union() {
Type::normalized_boolean_union_variants(discriminant_ty.flattened_union_variants().collect())
} else { vec![discriminant_ty] } so the logic around discriminant_ty,
normalized_boolean_union_variants, and flattened_union_variants remains the same
but uses an idiomatic if/else.
- Around line 259-280: The loop variable name `ty` is misleading because `state`
is a Vec<MissingCase>; rename the binding to `case` (or `missing`) in the for
loop and update all uses inside the block — e.g., change `for ty in state {` to
`for case in state {` and replace `missing_case_to_expression(ty)?` with
`missing_case_to_expression(case)?` (also update any other occurrences of `ty`
inside this block such as in the `clause` construction that references
`throw_stmt`/`clauses`), keeping the same logic and types.
- Around line 166-188: The loop variable name intersection_part is misleading
now that it iterates union variants; rename the loop variable to variant and
update all uses accordingly (e.g., change for intersection_part in variants to
for variant in variants, then call flatten_type(&variant) and update subsequent
checks and contains calls to use the new name or a clearly named flattened
variable such as flat_variant), ensuring references to has_boolean_case,
missing_cases.push(MissingCase::BooleanLiteral(...)), found_cases.contains(...),
and missing_cases.push(MissingCase::Type(...)) use the updated identifier names
so the code remains correct and readable.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 27481a2e-92b3-4206-9361-79dcca8edce8
⛔ Files ignored due to path filters (1)
crates/biome_js_analyze/tests/specs/nursery/useExhaustiveSwitchCases/valid.ts.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (2)
crates/biome_js_analyze/src/lint/nursery/use_exhaustive_switch_cases.rscrates/biome_js_analyze/tests/specs/nursery/useExhaustiveSwitchCases/valid.ts
✅ Files skipped from review due to trivial changes (1)
- crates/biome_js_analyze/tests/specs/nursery/useExhaustiveSwitchCases/valid.ts
cf2b724 to
17878b6
Compare
17878b6 to
c37bd08
Compare
c37bd08 to
b0f1701
Compare
…eturn-type-boolean-union # Conflicts: # crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/invalid.ts # crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/invalid.ts.snap # crates/biome_js_type_info/src/globals.rs # crates/biome_js_type_info/src/globals_ids.rs
Resolved conflicts in noMisleadingReturnType/invalid.ts and its snapshot. Kept this branch's union-bailout test cases and added upstream's partialBooleanUnion/ternaryBoolean cases from biomejs#10115. Snapshot regenerated via INSTA_UPDATE=always; all flagged cases preserved.
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
I used Claude Code to assist with this implementation.
Summary
Addresses items from #9810:
noMisleadingReturnTypeno longer reports a false positive when a union return type'sbooleanvariant is covered by bothtrueandfalsereturns.The canonicalization happens in
TypeData::union_of(true | false → boolean).useExhaustiveSwitchCasesnow flags missingtrue/falsecases onbooleandiscriminants, including whenbooleanis a union variant.Test Plan
Snapshot tests.