fix(lint): fix false negative in noMisleadingReturnType for union annotations#10052
Conversation
🦋 Changeset detectedLatest commit: 6314e3d 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 |
|
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 change updates the noMisleadingReturnType lint to detect annotated union return types that include variants never returned and to suggest narrowed return types. It adds Possibly related PRs
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.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rs (1)
587-706:⚠️ Potential issue | 🟡 MinorRender
null,undefined, andbigintliterals in narrowed suggestions.Covered annotation variants containing
null/undefinedcurrently fail theall_renderablecheck becauseis_variant_renderabledoesn't accept them, causing diagnostics to fall back to generic "Narrow the return type" messages. Similarly,Literal::BigIntis not handled inappend_literal, so bigint return diagnostics lose concrete suggestions like1n | 2n.Suggested direction
fn append_literal(result: &mut String, literal: &Literal) -> Option<()> { match literal { Literal::String(value) => { result.push('"'); result.push_str(value.as_str()); result.push('"'); } Literal::Number(value) => result.push_str(value.as_str()), + Literal::BigInt(value) => result.push_str(value.as_str()), Literal::Boolean(value) => { result.push_str(if value.as_bool() { "true" } else { "false" }) } _ => return None, } @@ match &**variant { - TypeData::String | TypeData::Number | TypeData::Boolean | TypeData::BigInt => true, + TypeData::String + | TypeData::Number + | TypeData::Boolean + | TypeData::BigInt + | TypeData::Null + | TypeData::Undefined + | TypeData::VoidKeyword => true, TypeData::Literal(literal) => matches!( literal.as_ref(), - Literal::String(_) | Literal::Number(_) | Literal::Boolean(_) + Literal::String(_) | Literal::Number(_) | Literal::Boolean(_) | Literal::BigInt(_) ), _ => false, } } @@ TypeData::Boolean => result.push_str("boolean"), TypeData::BigInt => result.push_str("bigint"), + TypeData::Null => result.push_str("null"), + TypeData::Undefined | TypeData::VoidKeyword => result.push_str("undefined"), TypeData::Literal(literal) => append_literal(&mut result, literal.as_ref())?, _ => return None, }🤖 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` around lines 587 - 706, The diagnostic rendering currently rejects null/undefined and bigint literal variants; update append_literal to handle Literal::Null (push "null"), Literal::Undefined (push "undefined"), and Literal::BigInt (push the value with trailing "n"), and update is_variant_renderable to treat Literal::BigInt, Literal::Null, and Literal::Undefined as renderable (in addition to existing Literal::String/Number/Boolean and TypeData::BigInt), so build_narrowed_annotation_description can include concrete "null", "undefined", and bigint literals in suggested narrowed types.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@crates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rs`:
- Around line 587-706: The diagnostic rendering currently rejects null/undefined
and bigint literal variants; update append_literal to handle Literal::Null (push
"null"), Literal::Undefined (push "undefined"), and Literal::BigInt (push the
value with trailing "n"), and update is_variant_renderable to treat
Literal::BigInt, Literal::Null, and Literal::Undefined as renderable (in
addition to existing Literal::String/Number/Boolean and TypeData::BigInt), so
build_narrowed_annotation_description can include concrete "null", "undefined",
and bigint literals in suggested narrowed types.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d6657d5a-19ad-406b-b8a8-79270c2c4bda
⛔ Files ignored due to path filters (2)
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**
📒 Files selected for processing (4)
.changeset/lazy-days-know.mdcrates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rscrates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/invalid.tscrates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/valid.ts
Merging this PR will not alter performance
Comparing Footnotes
|
0ee7514 to
da9a9ce
Compare
d219127 to
35c0efe
Compare
ematipico
left a comment
There was a problem hiding this comment.
I love the improvements; the allocation of a String is concerning. I suggested a different approach. Still, it's worth documenting the possible description limitation in the docs
|
|
||
| /// Upper bound on a narrowed return-type suggestion; longer unions fall back | ||
| /// to the generic diagnostic note. | ||
| const MAX_DESCRIPTION_LENGTH: usize = 80; |
There was a problem hiding this comment.
That's something worth mentioning in the docs. Maybe we could have a small header called ## Known limitations or something.
Internally, it's a technical thing, but I'm sure we can explain it to users. I bet this is something that power users will understand
| } | ||
|
|
||
| /// Drops annotation union variants not covered by any return. | ||
| fn build_narrowed_annotation_description( |
There was a problem hiding this comment.
The problem of this method is that it build a string that is not even consumed because we then use its reference.
Instead, you should implement the biome_console::fmt::Display trait, so that you can use fmt.write_str at will, without allocating strings.
You could implement it for RuleState like this (pseudo-code):
impl biome_console::fmt::Display for RuleState {
fn fmt(&self, f: Formatter) -> Result {
if self.has_any_const_return {
self.build_inferred_description(f)
}
}
}
impl RuleState {
fn build_inferred_description(&self, f: Formatter) -> Result {
// ..
}
}There was a problem hiding this comment.
Thanks for feedback. I refactored in 7981fc5.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rs (1)
671-678:⚠️ Potential issue | 🟡 MinorApply the same safety filter to narrowed suggestions.
build_inferred_descriptionsuppresses confusing suggestions such as...,__internal, andtypeof import(, but the new narrowed path can still emit them. Reuse the same guard before returning the narrowed description.🛡️ Proposed consistency fix
+fn is_safe_description(result: &str) -> bool { + !result.contains("...") + && !result.contains("__internal") + && !result.contains("typeof import(") +} + /// Builds a string like `"loading" | "idle"` for the diagnostic note. fn build_inferred_description(returns: &[Type]) -> Option<String> { @@ - if result.contains("...") || result.contains("__internal") || result.contains("typeof import(") { + if !is_safe_description(&result) { return None; } @@ - if result.len() > MAX_DESCRIPTION_LENGTH { + if !is_safe_description(&result) || result.len() > MAX_DESCRIPTION_LENGTH { return None; }Also applies to: 742-758
🤖 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` around lines 671 - 678, In build_inferred_description, guard the narrowed suggestion with the same safety checks used for result: before returning the narrowed description (the variable named narrowed or similar), check if it contains "..." or "__internal" or "typeof import(" or exceeds MAX_DESCRIPTION_LENGTH and return None if so; apply the identical checks in the other narrowed-return site referenced around the 742-758 area so both the primary result and the narrowed suggestion are filtered consistently.
🤖 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/nursery/no_misleading_return_type.rs`:
- Around line 635-650: The append_literal function currently inserts string
literal content verbatim; change append_literal to escape special characters (at
least backslash, double quote, newline, carriage return, tab) when handling
Literal::String so the wrapped suggestion becomes a valid Rust/JS string (e.g.,
replace \ with \\, " with \", \n with \\n, etc.) before pushing the surrounding
quotes; update the Literal::String arm in append_literal accordingly and keep
returning Some(()); also add snapshot tests for the no_misleading_return_type
rule that include strings containing escaped characters (newlines, quotes,
backslashes) to cover these edge cases in the rule's test suite.
---
Outside diff comments:
In `@crates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rs`:
- Around line 671-678: In build_inferred_description, guard the narrowed
suggestion with the same safety checks used for result: before returning the
narrowed description (the variable named narrowed or similar), check if it
contains "..." or "__internal" or "typeof import(" or exceeds
MAX_DESCRIPTION_LENGTH and return None if so; apply the identical checks in the
other narrowed-return site referenced around the 742-758 area so both the
primary result and the narrowed suggestion are filtered consistently.
🪄 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: 85281b31-2ff5-49eb-a947-8aa0e5b16b25
📒 Files selected for processing (1)
crates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rs
| /// Appends a primitive literal's display form. | ||
| fn append_literal(result: &mut String, literal: &Literal) -> Option<()> { | ||
| match literal { | ||
| Literal::String(value) => { | ||
| result.push('"'); | ||
| result.push_str(value.as_str()); | ||
| result.push('"'); | ||
| } | ||
| Literal::Number(value) => result.push_str(value.as_str()), | ||
| Literal::Boolean(value) => { | ||
| result.push_str(if value.as_bool() { "true" } else { "false" }) | ||
| } | ||
| _ => return None, | ||
| } | ||
| Some(()) | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Confirm whether string literal rendering still writes the raw payload
# and whether noMisleadingReturnType snapshots cover escaped string suggestions.
rg -n -C 4 'Literal::String\(value\)|push_str\(value\.as_str\(\)\)' \
crates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rs
rg -n -C 2 'escape|quote|backslash|\\\\|\\\"' \
crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType || trueRepository: biomejs/biome
Length of output: 768
🏁 Script executed:
# Find Literal enum definition
rg -n 'enum Literal|pub enum Literal' crates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rs -A 10Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Check where Literal::String is created in this file
rg -n 'Literal::String' crates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rs | head -20Repository: biomejs/biome
Length of output: 256
🏁 Script executed:
# Look at snapshot tests - find the test file
fd -t f 'noMisleadingReturnType' crates/biome_js_analyze/tests/ 2>/dev/nullRepository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Search for string escaping patterns elsewhere in biome
rg -n 'escape.*literal|quote.*string' crates/ -t rs | grep -i 'string\|escape' | head -15Repository: biomejs/biome
Length of output: 83
🏁 Script executed:
# Find where Literal is defined
rg -n 'enum Literal' crates/ -A 15 | head -40Repository: biomejs/biome
Length of output: 1238
🏁 Script executed:
# Check the snapshot test directory structure
find crates/biome_js_analyze/tests/specs/nursery -type f -name '*noMisleading*' 2>/dev/nullRepository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Look for string escaping in literal handling elsewhere
rg -n 'escape|StringValue' crates/biome_js_analyze/src/ -A 2 -B 2 | head -50Repository: biomejs/biome
Length of output: 5040
🏁 Script executed:
# Check where this Literal comes from in the file - look for imports
head -30 crates/biome_js_analyze/src/lint/nursery/no_misleading_return_type.rsRepository: biomejs/biome
Length of output: 1350
🏁 Script executed:
# Find StringLiteral definition
rg -n 'struct StringLiteral|pub struct StringLiteral' crates/biome_js_type_info/src/ -A 5Repository: biomejs/biome
Length of output: 511
🏁 Script executed:
# Check what as_str() does for StringLiteral
rg -n 'impl.*StringLiteral|fn as_str' crates/biome_js_type_info/src/type_data.rs -A 10Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Find actual snapshot test files
find crates/biome_js_analyze/tests -type d -name '*nursery*' | head -5Repository: biomejs/biome
Length of output: 100
🏁 Script executed:
# Look for the actual test insta snapshots
find crates/biome_js_analyze/tests -type f -name '*.txt' | grep -i misleading | head -10Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Find Text type definition
rg -n 'struct Text|pub struct Text' crates/ -A 8 | head -40Repository: biomejs/biome
Length of output: 2328
🏁 Script executed:
# Look directly in the nursery test specs directory
ls -la crates/biome_js_analyze/tests/specs/nursery/ | grep -i misleadingRepository: biomejs/biome
Length of output: 129
🏁 Script executed:
# Check what files exist in the nursery directory
ls crates/biome_js_analyze/tests/specs/nursery/ | head -30Repository: biomejs/biome
Length of output: 626
🏁 Script executed:
# Look for any test snapshot files related to misleading
find crates/biome_js_analyze/tests -name '*misleading*' -type fRepository: biomejs/biome
Length of output: 39
🏁 Script executed:
# List files in the test directory
ls -la crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/Repository: biomejs/biome
Length of output: 426
🏁 Script executed:
# Look at one or two of the snapshot files to understand format
head -100 crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/valid.json 2>/dev/null || \
head -100 crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/invalid.json 2>/dev/null || \
cat crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/* 2>/dev/null | head -150Repository: biomejs/biome
Length of output: 5738
🏁 Script executed:
# Search for Text type definition - likely in biome_rowan or biome_js_syntax
rg -n 'pub struct Text|impl Text' crates/biome_rowan/ crates/biome_js_syntax/ -A 5 | head -40Repository: biomejs/biome
Length of output: 787
🏁 Script executed:
# Check if there are any test inputs or output files with special characters
find crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType -type f -exec grep -l 'escape\|backslash\|\\\\"' {} \;Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Find the text() method implementation in Text
rg -n 'pub fn text|fn text' crates/biome_rowan/src/text.rs -A 5Repository: biomejs/biome
Length of output: 320
🏁 Script executed:
# Check how JS string literals are parsed - look in js_syntax or parser
rg -n 'JsString|parse.*string' crates/biome_js_syntax/src/ | head -20Repository: biomejs/biome
Length of output: 2317
🏁 Script executed:
# Look at the snapshot output to see what suggestions are generated
sed -n '1,300p' crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/invalid.ts.snap | grep -A 10 'suggestion\|message'Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Search for any test case with escaped strings or special characters
grep -n '\\\\' crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/*.ts || echo "No escaped strings found in test files"Repository: biomejs/biome
Length of output: 95
🏁 Script executed:
# Find where StringLiteral is constructed - look in type_info module
rg -n 'StringLiteral(' crates/biome_js_type_info/src/ -B 3 -A 3 | head -60Repository: biomejs/biome
Length of output: 135
🏁 Script executed:
# Look at the snapshot output to see what suggested types look like
sed -n '1,500p' crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/invalid.ts.snap | tail -200Repository: biomejs/biome
Length of output: 8725
🏁 Script executed:
# Check for how the string value is extracted from JS syntax
rg -n 'value_token|as_str\(\)' crates/biome_js_type_info/src/ -B 2 -A 5 | head -80Repository: biomejs/biome
Length of output: 7881
🏁 Script executed:
# Search snapshot output for any string suggestions that might have special chars
grep -n 'Consider using "' crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/invalid.ts.snap | head -20Repository: biomejs/biome
Length of output: 1142
🏁 Script executed:
# Check if there's a test with newline or quote characters
grep -E '\\n|\\"|\\\\' crates/biome_js_analyze/tests/specs/nursery/noMisleadingReturnType/invalid.ts.snapRepository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Look at inner_string_text documentation or implementation
rg -n 'inner_string_text' crates/biome_js_syntax/src/ -A 3 | head -40Repository: biomejs/biome
Length of output: 3342
Escape string content when wrapping with quotes, and add test cases covering strings with special characters.
The append_literal function appends inner_string_text() directly without unescaping. For a source string like "hello\nworld", this generates an invalid suggestion "hello\nworld" (with the escape sequence still present). The code should either unescape the content before wrapping or escape special characters (newlines, quotes, backslashes) when constructing the type suggestion.
Additionally, the snapshot tests lack coverage for strings containing escaped characters (newlines, quotes, backslashes). Per the coding guidelines, all code changes should include appropriate snapshot tests covering valid and edge cases.
Suggested approach
Use unescaping when appending string literals:
+fn append_string_literal_content(result: &mut String, value: &str) {
+ for ch in value.chars() {
+ match ch {
+ '\\' => result.push_str("\\\\"),
+ '"' => result.push_str("\\\""),
+ '\n' => result.push_str("\\n"),
+ '\r' => result.push_str("\\r"),
+ '\t' => result.push_str("\\t"),
+ _ => result.push(ch),
+ }
+ }
+}
+
fn append_literal(result: &mut String, literal: &Literal) -> Option<()> {
match literal {
Literal::String(value) => {
result.push('"');
- result.push_str(value.as_str());
+ append_string_literal_content(result, value.as_str());
result.push('"');
}Add test cases with escaped strings to tests/specs/nursery/noMisleadingReturnType/invalid.ts.
🤖 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` around
lines 635 - 650, The append_literal function currently inserts string literal
content verbatim; change append_literal to escape special characters (at least
backslash, double quote, newline, carriage return, tab) when handling
Literal::String so the wrapped suggestion becomes a valid Rust/JS string (e.g.,
replace \ with \\, " with \", \n with \\n, etc.) before pushing the surrounding
quotes; update the Literal::String arm in append_literal accordingly and keep
returning Some(()); also add snapshot tests for the no_misleading_return_type
rule that include strings containing escaped characters (newlines, quotes,
backslashes) to cover these edge cases in the rule's test suite.
ematipico
left a comment
There was a problem hiding this comment.
The code has some silly mistakes 😅
| impl biome_console::fmt::Display for RuleState { | ||
| fn fmt(&self, formatter: &mut biome_console::fmt::Formatter<'_>) -> std::io::Result<()> { |
There was a problem hiding this comment.
Can you import all of these at the top and remove all those inline biome_console?
There was a problem hiding this comment.
Fixed in 7be5826. I moved the fmt imports to the top and removed the inline biome_console paths.
| /// Writes a string/number/boolean literal; writes nothing for other kinds. | ||
| fn write_literal( | ||
| formatter: &mut biome_console::fmt::Formatter<'_>, | ||
| literal: &Literal, | ||
| ) -> std::io::Result<()> { |
There was a problem hiding this comment.
Why don't you keep all the write methods close together? You can use region comments to set boundaries
// #region display methods
// impl Display
// write_narrow
// #endregion| TypeData::String => Some("string".len()), | ||
| TypeData::Number => Some("number".len()), | ||
| TypeData::BigInt => Some("bigint".len()), | ||
| TypeData::Boolean => Some("boolean".len()), |
There was a problem hiding this comment.
Many of these can be hardcoded. We know the length of string, for example. Are you checking the code emitted by your agent??? 😅😅😅😅
There was a problem hiding this comment.
I was testing a few approaches here and left in code that wasn’t cleaned up enough. Sorry for the noise and for taking your review time. I’ll simplify this and review it more carefully before requesting review again.😢😢
There was a problem hiding this comment.
Fixed in 7be5826. I replaced the obvious .len() calls with hardcoded values.
6008b99 to
cefe669
Compare
5e37ec4 to
3d79cd1
Compare
|
Needs rebase |
58c5d03 to
1a680cf
Compare
|
@ematipico Rebase completed. |
1a680cf to
8ac12b0
Compare
| /// | ||
| /// ## Known limitations | ||
| /// | ||
| /// Suggested replacement types are only shown when their textual |
There was a problem hiding this comment.
Github doesn't allow me to edit the whole block, but I think we should make a list for each known limitation e.g.
## Known limitations
- Suggested...
- When...
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [@biomejs/biome](https://biomejs.dev) ([source](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome)) | imports | patch | [`2.4.14` -> `2.4.15`](https://renovatebot.com/diffs/npm/@biomejs%2fbiome/2.4.14/2.4.15) | --- ### Release Notes <details> <summary>biomejs/biome (@​biomejs/biome)</summary> ### [`v2.4.15`](https://github.com/biomejs/biome/blob/HEAD/packages/@​biomejs/biome/CHANGELOG.md#2415) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.4.14...@biomejs/biome@2.4.15) ##### Patch Changes - [#​9394](biomejs/biome#9394) [`ba3480e`](biomejs/biome@ba3480e) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`useTestHooksInOrder`](https://biomejs.dev/linter/rules/use-test-hooks-in-order) in the `test` domain. The rule enforces that Jest/Vitest lifecycle hooks (`beforeAll`, `beforeEach`, `afterEach`, `afterAll`) are declared in the order they execute, making test setup and teardown easier to reason about. - [#​10254](biomejs/biome#10254) [`e0a54cc`](biomejs/biome@e0a54cc) Thanks [@​dyc3](https://github.com/dyc3)! - Added a new nursery rule [`useVueNextTickPromise`](https://biomejs.dev/linter/rules/use-vue-next-tick-promise/), which enforces Promise syntax when using Vue `nextTick`. For example, the following snippet triggers the rule: ```js import { nextTick } from "vue"; nextTick(() => { updateDom(); }); ``` - [#​10219](biomejs/biome#10219) [`64aee45`](biomejs/biome@64aee45) Thanks [@​dyc3](https://github.com/dyc3)! - Added a new nursery rule [`noVueVOnNumberValues`](https://biomejs.dev/linter/rules/no-vue-v-on-number-values/), that disallows deprecated number modifiers on Vue `v-on` directives. For example, the following snippet triggers the rule: ```vue <input @​keyup.13="submit" /> ``` - [#​10195](biomejs/biome#10195) [`7b8d4e1`](biomejs/biome@7b8d4e1) Thanks [@​dyc3](https://github.com/dyc3)! - Added the new nursery rule [`useVueValidVFor`](https://biomejs.dev/linter/rules/use-vue-valid-v-for/), which validates Vue `v-for` directives and reports invalid aliases, missing component keys, and keys that do not use iteration variables. - [#​10238](biomejs/biome#10238) [`1110256`](biomejs/biome@1110256) Thanks [@​dyc3](https://github.com/dyc3)! - Added the recommended nursery rule [`noVueImportCompilerMacros`](https://biomejs.dev/linter/rules/no-vue-import-compiler-macros/), which disallows importing Vue compiler macros such as `defineProps` from `vue` because they are automatically available. - [#​10201](biomejs/biome#10201) [`1a08f89`](biomejs/biome@1a08f89) Thanks [@​realknove](https://github.com/realknove)! - Fixed [#​10193](biomejs/biome#10193): `style/useReadonlyClassProperties` no longer reports class properties as readonly-able when they are assigned inside arrow callbacks nested in class property initializers. - [#​9574](biomejs/biome#9574) [`3bd2b6a`](biomejs/biome@3bd2b6a) Thanks [@​Conaclos](https://github.com/Conaclos)! - Fixed [#​9530](biomejs/biome#9530). The diagnostics of [`organizeImports`](https://biomejs.dev/assist/actions/organize-imports/) are now more detailed and more precise. They are also better at localizing where the issue is. - [#​10205](biomejs/biome#10205) [`a704a6c`](biomejs/biome@a704a6c) Thanks [@​Conaclos](https://github.com/Conaclos)! - Fixed [#​10185](biomejs/biome#10185). [\`organizeImports](https://biomejs.dev/assist/actions/organize-imports/) now errors when it encounters an unknown predefined group. The following configuration is now reported as invalid because `:INEXISTENT:` is an unknown predefined group. ```json { "assist": { "actions": { "source": { "organizeImports": { "options": { "groups": [":INEXISTENT:"] } } } } } } ``` - [#​10052](biomejs/biome#10052) [`b565bed`](biomejs/biome@b565bed) Thanks [@​minseong0324](https://github.com/minseong0324)! - Improved [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/): it now flags union annotations whose extra variants are never returned, and suggests the narrower type (e.g. `string | null` → `string`). These functions are now reported because `null` and `number` are included in the return annotations but never returned: ```ts function getUser(): string | null { return "hello"; } // null is never returned function getCode(): string | number { return "hello"; } // number is never returned ``` - [#​10213](biomejs/biome#10213) [`ac30057`](biomejs/biome@ac30057) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​9450](biomejs/biome#9450): HTML and Vue element formatting now preserves child line breaks when an element contains another element child on its own line, instead of collapsing the child element onto the same line. - [#​10275](biomejs/biome#10275) [`9ee6c03`](biomejs/biome@9ee6c03) Thanks [@​solithcy](https://github.com/solithcy)! - Fixed [#​10274](biomejs/biome#10274): Svelte templates with missing expressions no longer parsed as `HtmlBogusElement` - [#​10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) now detects misleading return type annotations when object literal properties are initialized with `as const`. This function is now reported because the return annotation widens a property initialized with `as const`: ```ts function f(): { value: string } { return { value: "text" as const }; } ``` - [#​10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`noUselessTypeConversion`](https://biomejs.dev/linter/rules/no-useless-type-conversion/) now detects redundant conversions on object literal properties initialized with `as const`. This conversion is now reported because `message.value` is inferred as a string literal: ```ts const message = { value: "text" as const }; String(message.value); ``` - [#​9807](biomejs/biome#9807) [`0ae5840`](biomejs/biome@0ae5840) Thanks [@​dyc3](https://github.com/dyc3)! - Added the new nursery rule [`useThisInClassMethods`](https://biomejs.dev/linter/rules/use-this-in-class-methods/), based on ESLint's `class-methods-use-this`. The rule now reports instance methods, getters, setters, and function-valued instance fields that do not use `this`, and `biome migrate eslint` preserves the supported `ignoreMethods`, `ignoreOverrideMethods`, and `ignoreClassesWithImplements` options. **Invalid**: ```js class Foo { bar() { // does not use `this`, invalid console.log("Hello Biome"); } } ``` - [#​10258](biomejs/biome#10258) [`e7b18f7`](biomejs/biome@e7b18f7) Thanks [@​ematipico](https://github.com/ematipico)! - Improved linter performance by narrowing the query nodes for several lint rules, reducing how often they are evaluated. - [#​10273](biomejs/biome#10273) [`04e22a1`](biomejs/biome@04e22a1) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10271](biomejs/biome#10271): The HTML parser now correctly parses `of` as text content when in text contexts. - [#​9838](biomejs/biome#9838) [`83f7385`](biomejs/biome@83f7385) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`noBaseToString`](https://biomejs.dev/linter/rules/no-base-to-string/), which reports stringification sites that fall back to Object's default `"[object Object]"` formatting. The rule also supports the `ignoredTypeNames` option. - [#​10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`useExhaustiveSwitchCases`](https://biomejs.dev/linter/rules/use-exhaustive-switch-cases/) now checks switch statements over object literal properties initialized with `as const`. This switch is now reported because `status.kind` is inferred as the string literal `"ready"` but no case handles it: ```ts const status = { kind: "ready" as const }; switch (status.kind) { } ``` - [#​10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`useStringStartsEndsWith`](https://biomejs.dev/linter/rules/use-string-starts-ends-with/) now detects string index comparisons on object literal properties initialized with `as const`. This comparison is now reported because `message.value` is inferred as a string literal: ```ts const message = { value: "hello" as const }; message.value[0] === "h"; ``` </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNzMuMyIsInVwZGF0ZWRJblZlciI6IjQzLjE3My4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://git.oirnoir.dev/OIRNOIR/YouTube-Helper-Server/pulls/12
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [@biomejs/biome](https://biomejs.dev) ([source](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome)) | imports | patch | [`2.4.14` -> `2.4.15`](https://renovatebot.com/diffs/npm/@biomejs%2fbiome/2.4.14/2.4.15) | --- ### Release Notes <details> <summary>biomejs/biome (@​biomejs/biome)</summary> ### [`v2.4.15`](https://github.com/biomejs/biome/blob/HEAD/packages/@​biomejs/biome/CHANGELOG.md#2415) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.4.14...@biomejs/biome@2.4.15) ##### Patch Changes - [#​9394](biomejs/biome#9394) [`ba3480e`](biomejs/biome@ba3480e) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`useTestHooksInOrder`](https://biomejs.dev/linter/rules/use-test-hooks-in-order) in the `test` domain. The rule enforces that Jest/Vitest lifecycle hooks (`beforeAll`, `beforeEach`, `afterEach`, `afterAll`) are declared in the order they execute, making test setup and teardown easier to reason about. - [#​10254](biomejs/biome#10254) [`e0a54cc`](biomejs/biome@e0a54cc) Thanks [@​dyc3](https://github.com/dyc3)! - Added a new nursery rule [`useVueNextTickPromise`](https://biomejs.dev/linter/rules/use-vue-next-tick-promise/), which enforces Promise syntax when using Vue `nextTick`. For example, the following snippet triggers the rule: ```js import { nextTick } from "vue"; nextTick(() => { updateDom(); }); ``` - [#​10219](biomejs/biome#10219) [`64aee45`](biomejs/biome@64aee45) Thanks [@​dyc3](https://github.com/dyc3)! - Added a new nursery rule [`noVueVOnNumberValues`](https://biomejs.dev/linter/rules/no-vue-v-on-number-values/), that disallows deprecated number modifiers on Vue `v-on` directives. For example, the following snippet triggers the rule: ```vue <input @​keyup.13="submit" /> ``` - [#​10195](biomejs/biome#10195) [`7b8d4e1`](biomejs/biome@7b8d4e1) Thanks [@​dyc3](https://github.com/dyc3)! - Added the new nursery rule [`useVueValidVFor`](https://biomejs.dev/linter/rules/use-vue-valid-v-for/), which validates Vue `v-for` directives and reports invalid aliases, missing component keys, and keys that do not use iteration variables. - [#​10238](biomejs/biome#10238) [`1110256`](biomejs/biome@1110256) Thanks [@​dyc3](https://github.com/dyc3)! - Added the recommended nursery rule [`noVueImportCompilerMacros`](https://biomejs.dev/linter/rules/no-vue-import-compiler-macros/), which disallows importing Vue compiler macros such as `defineProps` from `vue` because they are automatically available. - [#​10201](biomejs/biome#10201) [`1a08f89`](biomejs/biome@1a08f89) Thanks [@​realknove](https://github.com/realknove)! - Fixed [#​10193](biomejs/biome#10193): `style/useReadonlyClassProperties` no longer reports class properties as readonly-able when they are assigned inside arrow callbacks nested in class property initializers. - [#​9574](biomejs/biome#9574) [`3bd2b6a`](biomejs/biome@3bd2b6a) Thanks [@​Conaclos](https://github.com/Conaclos)! - Fixed [#​9530](biomejs/biome#9530). The diagnostics of [`organizeImports`](https://biomejs.dev/assist/actions/organize-imports/) are now more detailed and more precise. They are also better at localizing where the issue is. - [#​10205](biomejs/biome#10205) [`a704a6c`](biomejs/biome@a704a6c) Thanks [@​Conaclos](https://github.com/Conaclos)! - Fixed [#​10185](biomejs/biome#10185). [\`organizeImports](https://biomejs.dev/assist/actions/organize-imports/) now errors when it encounters an unknown predefined group. The following configuration is now reported as invalid because `:INEXISTENT:` is an unknown predefined group. ```json { "assist": { "actions": { "source": { "organizeImports": { "options": { "groups": [":INEXISTENT:"] } } } } } } ``` - [#​10052](biomejs/biome#10052) [`b565bed`](biomejs/biome@b565bed) Thanks [@​minseong0324](https://github.com/minseong0324)! - Improved [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/): it now flags union annotations whose extra variants are never returned, and suggests the narrower type (e.g. `string | null` → `string`). These functions are now reported because `null` and `number` are included in the return annotations but never returned: ```ts function getUser(): string | null { return "hello"; } // null is never returned function getCode(): string | number { return "hello"; } // number is never returned ``` - [#​10213](biomejs/biome#10213) [`ac30057`](biomejs/biome@ac30057) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​9450](biomejs/biome#9450): HTML and Vue element formatting now preserves child line breaks when an element contains another element child on its own line, instead of collapsing the child element onto the same line. - [#​10275](biomejs/biome#10275) [`9ee6c03`](biomejs/biome@9ee6c03) Thanks [@​solithcy](https://github.com/solithcy)! - Fixed [#​10274](biomejs/biome#10274): Svelte templates with missing expressions no longer parsed as `HtmlBogusElement` - [#​10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) now detects misleading return type annotations when object literal properties are initialized with `as const`. This function is now reported because the return annotation widens a property initialized with `as const`: ```ts function f(): { value: string } { return { value: "text" as const }; } ``` - [#​10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`noUselessTypeConversion`](https://biomejs.dev/linter/rules/no-useless-type-conversion/) now detects redundant conversions on object literal properties initialized with `as const`. This conversion is now reported because `message.value` is inferred as a string literal: ```ts const message = { value: "text" as const }; String(message.value); ``` - [#​9807](biomejs/biome#9807) [`0ae5840`](biomejs/biome@0ae5840) Thanks [@​dyc3](https://github.com/dyc3)! - Added the new nursery rule [`useThisInClassMethods`](https://biomejs.dev/linter/rules/use-this-in-class-methods/), based on ESLint's `class-methods-use-this`. The rule now reports instance methods, getters, setters, and function-valued instance fields that do not use `this`, and `biome migrate eslint` preserves the supported `ignoreMethods`, `ignoreOverrideMethods`, and `ignoreClassesWithImplements` options. **Invalid**: ```js class Foo { bar() { // does not use `this`, invalid console.log("Hello Biome"); } } ``` - [#​10258](biomejs/biome#10258) [`e7b18f7`](biomejs/biome@e7b18f7) Thanks [@​ematipico](https://github.com/ematipico)! - Improved linter performance by narrowing the query nodes for several lint rules, reducing how often they are evaluated. - [#​10273](biomejs/biome#10273) [`04e22a1`](biomejs/biome@04e22a1) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10271](biomejs/biome#10271): The HTML parser now correctly parses `of` as text content when in text contexts. - [#​9838](biomejs/biome#9838) [`83f7385`](biomejs/biome@83f7385) Thanks [@​dyc3](https://github.com/dyc3)! - Added the nursery rule [`noBaseToString`](https://biomejs.dev/linter/rules/no-base-to-string/), which reports stringification sites that fall back to Object's default `"[object Object]"` formatting. The rule also supports the `ignoredTypeNames` option. - [#​10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`useExhaustiveSwitchCases`](https://biomejs.dev/linter/rules/use-exhaustive-switch-cases/) now checks switch statements over object literal properties initialized with `as const`. This switch is now reported because `status.kind` is inferred as the string literal `"ready"` but no case handles it: ```ts const status = { kind: "ready" as const }; switch (status.kind) { } ``` - [#​10143](biomejs/biome#10143) [`56798a7`](biomejs/biome@56798a7) Thanks [@​minseong0324](https://github.com/minseong0324)! - [`useStringStartsEndsWith`](https://biomejs.dev/linter/rules/use-string-starts-ends-with/) now detects string index comparisons on object literal properties initialized with `as const`. This comparison is now reported because `message.value` is inferred as a string literal: ```ts const message = { value: "hello" as const }; message.value[0] === "h"; ``` </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNzMuMyIsInVwZGF0ZWRJblZlciI6IjQzLjE3My4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Reviewed-on: https://git.oirnoir.dev/OIRNOIR/YouTube-Helper-Client/pulls/3
I used Claude Code to assist with this implementation.
Summary
Addresses items from #9810: Single-return bail-out for union annotations
Generic type-alias unions are tracked as follow-up in the same issue.
Test Plan
Snapshot tests.