feat(lint/js): add noBaseToString#9838
Conversation
Merging this PR will not alter performance
Comparing Footnotes
|
🦋 Changeset detectedLatest commit: 6ad86c2 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 |
c85b65d to
b1e5659
Compare
f68da94 to
f055aab
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:
WalkthroughAdds a new nursery lint rule 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)
Review rate limit: 4/5 reviews remaining, refill in 12 minutes. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
crates/biome_cli/tests/commands/migrate_eslint.rs (1)
421-443: Add an explicit success assert before snapshotting.
The test is great, but an upfrontassert!(result.is_ok(), ...)makes breakages fail faster and clearer.Suggested tweak
let (fs, result) = run_cli( fs, &mut console, Args::from( [ "migrate", "eslint", "--include-inspired", "--include-nursery", ] .as_slice(), ), ); + assert!(result.is_ok(), "run_cli returned {result:?}"); assert_cli_snapshot(SnapshotPayload::new( module_path!(), "migrate_eslintrcjson_nursery_rule_options", fs, console, result, ));🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/biome_cli/tests/commands/migrate_eslint.rs` around lines 421 - 443, Add an explicit success assertion for the CLI run result before snapshotting: after calling run_cli (the variable result returned by run_cli) insert an assertion like assert!(result.is_ok(), "migrate eslint failed: {:?}", result) so the test fails fast and shows the error before assert_cli_snapshot is invoked; keep the existing run_cli, BufferConsole, and SnapshotPayload usage and place the assert immediately prior to the assert_cli_snapshot call.crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs (1)
742-748: Consider removing the dead binding.The
let _ = saw_unknown;on line 745 suppresses an unused-variable warning, but the logic implicitly handles it via theNonereturn. This is fine, though a brief comment explaining thatNonecovers the unknown case would aid readability.💡 Optional: clarify intent
if saw_true { Some(true) } else { - let _ = saw_unknown; + // When no definitive `true` result was found, return `None` to signal + // uncertainty (possibly due to unresolved types). 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_base_to_string.rs` around lines 742 - 748, The binding let _ = saw_unknown; in the block that returns Some(true) / None is dead; remove that line and either rely on the None return to represent the unknown case or, if you want to clarify intent, replace the binding with a short comment (e.g. "None covers the unknown case") near the return to improve readability; locate this change around the saw_true / saw_unknown logic in no_base_to_string.rs.
🤖 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_cli/src/execute/migrate/eslint_typescript.rs`:
- Around line 10-14: The use declaration imports several symbols from
biome_rule_options twice, causing E0252; edit the use statement in the module to
remove the duplicated specifiers—keep a single instance of each symbol
(no_base_to_string, no_shadow, use_consistent_array_type,
use_consistent_member_accessibility, use_import_type, use_naming_convention) in
the use biome_rule_options::{...} list so each name is only imported once.
---
Nitpick comments:
In `@crates/biome_cli/tests/commands/migrate_eslint.rs`:
- Around line 421-443: Add an explicit success assertion for the CLI run result
before snapshotting: after calling run_cli (the variable result returned by
run_cli) insert an assertion like assert!(result.is_ok(), "migrate eslint
failed: {:?}", result) so the test fails fast and shows the error before
assert_cli_snapshot is invoked; keep the existing run_cli, BufferConsole, and
SnapshotPayload usage and place the assert immediately prior to the
assert_cli_snapshot call.
In `@crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs`:
- Around line 742-748: The binding let _ = saw_unknown; in the block that
returns Some(true) / None is dead; remove that line and either rely on the None
return to represent the unknown case or, if you want to clarify intent, replace
the binding with a short comment (e.g. "None covers the unknown case") near the
return to improve readability; locate this change around the saw_true /
saw_unknown logic in no_base_to_string.rs.
🪄 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: 00bf0213-2242-494b-8e55-aeafdc4346f6
⛔ Files ignored due to path filters (11)
crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rsis excluded by!**/migrate/eslint_any_rule_to_biome.rsand included by**crates/biome_cli/tests/snapshots/main_commands_migrate_eslint/migrate_eslintrcjson_nursery_rule_options.snapis excluded by!**/*.snapand included by**crates/biome_configuration/src/analyzer/linter/rules.rsis excluded by!**/rules.rsand included by**crates/biome_configuration/src/generated/domain_selector.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_configuration/src/generated/linter_options_check.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_diagnostics_categories/src/categories.rsis excluded by!**/categories.rsand included by**crates/biome_js_analyze/tests/specs/nursery/noBaseToString/invalid.ts.snapis excluded by!**/*.snapand included by**crates/biome_js_analyze/tests/specs/nursery/noBaseToString/valid.ts.snapis excluded by!**/*.snapand included by**crates/biome_js_analyze/tests/specs/nursery/noBaseToString/validIgnoredTypeNames.ts.snapis excluded by!**/*.snapand included by**packages/@biomejs/backend-jsonrpc/src/workspace.tsis excluded by!**/backend-jsonrpc/src/workspace.tsand included by**packages/@biomejs/biome/configuration_schema.jsonis excluded by!**/configuration_schema.jsonand included by**
📒 Files selected for processing (12)
.changeset/tidy-lamps-bake.mdcrates/biome_cli/src/execute/migrate/eslint_eslint.rscrates/biome_cli/src/execute/migrate/eslint_to_biome.rscrates/biome_cli/src/execute/migrate/eslint_typescript.rscrates/biome_cli/tests/commands/migrate_eslint.rscrates/biome_js_analyze/src/lint/nursery/no_base_to_string.rscrates/biome_js_analyze/tests/specs/nursery/noBaseToString/invalid.tscrates/biome_js_analyze/tests/specs/nursery/noBaseToString/valid.tscrates/biome_js_analyze/tests/specs/nursery/noBaseToString/validIgnoredTypeNames.options.jsoncrates/biome_js_analyze/tests/specs/nursery/noBaseToString/validIgnoredTypeNames.tscrates/biome_rule_options/src/lib.rscrates/biome_rule_options/src/no_base_to_string.rs
3ec6eb5 to
a5aa0f9
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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_base_to_string.rs`:
- Around line 111-112: The current logic stops at the first bad interpolation
because it uses a find_map-style short-circuit; change it so every offending
interpolation is reported: in the JsTemplateExpression match arm
(AnyNoBaseToStringQuery::JsTemplateExpression) and the similar block around
lines 289-299, have run_template_expression(ctx, template) produce/return all
diagnostics (or an iterator of Signals) and collect them (e.g., via
.into_iter().flat_map(...) or .filter_map(...) and collect/extend into the
diagnostics Vec) instead of using find_map; update run_template_expression
internals if necessary to yield one entry per bad interpolation so all `${...}`
occurrences are reported.
- Around line 230-234: The logic treating direct
`.toString()`/`.toLocaleString()` calls as safe when an object only defines
`valueOf()` is incorrect; update the code paths that handle property_name
"toString" and "toLocaleString" (the match arm calling check_expression with
DiagnosticKind::BaseToString) to use a check that only considers an actual
custom toString member rather than has_custom_stringification_member() (which
conflates valueOf). Either add a new helper like has_custom_to_string_member()
that looks for an explicit toString/toLocaleString definition or change the
existing helper to accept a flag for direct-call semantics, and replace uses at
the shown match (and the other occurrences around lines ~487–495 and ~750–756)
so direct calls are only considered safe when a true custom
toString/toLocaleString exists.
- Around line 355-356: The current exemption checks in is_literal_expression
allow array literals to be treated as literals, which lets expressions like
String([{}]) bypass the rule; update is_literal_expression (and any helper
checks it uses) to stop treating array/array literal AST nodes as literal
expressions so arrays are not exempted—specifically, remove or change the branch
that matches array literal node kinds (e.g., ArrayExpression/ArrayLiteral) so
that is_literal_expression returns false for arrays while still returning true
for true primitives (strings, numbers, booleans, null, regex, template-only
literals) and for the same symbol names used at the call site (the expression
variable in no_base_to_string.rs).
- Around line 579-588: The combine_intersection function currently collapses any
non-Always certainty to Never and thus loses Sometimes; update
combine_intersection so it first returns Usefulness::Always if any constituent
is Always, otherwise returns Usefulness::Sometimes if any constituent is
Sometimes, and only returns Usefulness::Never when all constituents are Never;
update the iterator checks in combine_intersection to test for Always first,
then for Sometimes (e.g., using any on the iterator or by collecting into a
small temp vector/iterator clone) so that Sometimes is preserved through
intersections.
🪄 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: d54df07e-d800-4d1c-a500-01c757df5b76
📒 Files selected for processing (2)
crates/biome_cli/src/execute/migrate/eslint_typescript.rscrates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs
🚧 Files skipped from review as they are similar to previous changes (1)
- crates/biome_cli/src/execute/migrate/eslint_typescript.rs
| AnyNoBaseToStringQuery::JsTemplateExpression(template) => { | ||
| run_template_expression(ctx, template).into_iter().collect() |
There was a problem hiding this comment.
Report every bad interpolation in a template.
find_map stops at the first failing ${...}, so a template like `${a}${b}` only yields one diagnostic even though Signals can carry several. The second offender gets a free pass.
Possible fix
- AnyNoBaseToStringQuery::JsTemplateExpression(template) => {
- run_template_expression(ctx, template).into_iter().collect()
- }
+ AnyNoBaseToStringQuery::JsTemplateExpression(template) => {
+ run_template_expression(ctx, template).into_boxed_slice()
+ }
-fn run_template_expression(
+fn run_template_expression(
ctx: &RuleContext<NoBaseToString>,
node: &JsTemplateExpression,
-) -> Option<RuleState> {
+) -> Vec<RuleState> {
if node.tag().is_some() {
- return None;
+ return Vec::new();
}
node.elements()
.into_iter()
- .find_map(|element| match element {
+ .filter_map(|element| match element {
AnyJsTemplateElement::JsTemplateElement(template_element) => {
template_element.expression().ok().and_then(|expression| {
check_expression(ctx, &expression, DiagnosticKind::BaseToString)
})
}
AnyJsTemplateElement::JsTemplateChunkElement(_) => None,
})
+ .collect()
}Also applies to: 289-299
🤖 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_base_to_string.rs` around lines
111 - 112, The current logic stops at the first bad interpolation because it
uses a find_map-style short-circuit; change it so every offending interpolation
is reported: in the JsTemplateExpression match arm
(AnyNoBaseToStringQuery::JsTemplateExpression) and the similar block around
lines 289-299, have run_template_expression(ctx, template) produce/return all
diagnostics (or an iterator of Signals) and collect them (e.g., via
.into_iter().flat_map(...) or .filter_map(...) and collect/extend into the
diagnostics Vec) instead of using find_map; update run_template_expression
internals if necessary to yield one entry per bad interpolation so all `${...}`
occurrences are reported.
| match property_name { | ||
| "join" => check_expression(ctx, &object, DiagnosticKind::BaseArrayJoin), | ||
| "toString" | "toLocaleString" => { | ||
| check_expression(ctx, &object, DiagnosticKind::BaseToString) | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
wc -l crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 123
🏁 Script executed:
head -n 300 crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs | tail -n 100Repository: biomejs/biome
Length of output: 3051
🏁 Script executed:
sed -n '220,250p' crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 1041
🏁 Script executed:
sed -n '475,510p' crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 1528
🏁 Script executed:
sed -n '740,765p' crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 803
🏁 Script executed:
sed -n '400,500p' crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 4255
🏁 Script executed:
sed -n '150,250p' crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 2937
🏁 Script executed:
sed -n '480,510p' crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 1267
🏁 Script executed:
sed -n '550,650p' crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 3220
🏁 Script executed:
grep -n "is_to_string_like_from_object" crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 243
🏁 Script executed:
sed -n '642,750p' crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 3602
🏁 Script executed:
sed -n '1,100p' crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 3203
🏁 Script executed:
grep -n "DiagnosticKind::" crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 902
valueOf() should not silence explicit .toString() calls.
Direct obj.toString() never consults valueOf(), but the coercion algorithm does. The analysis currently treats both contexts with the same code path via has_custom_stringification_member(), so objects with only valueOf() defined are incorrectly marked as safe for direct calls, creating false negatives.
Also applies to: 487–495, 750–756
🤖 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_base_to_string.rs` around lines
230 - 234, The logic treating direct `.toString()`/`.toLocaleString()` calls as
safe when an object only defines `valueOf()` is incorrect; update the code paths
that handle property_name "toString" and "toLocaleString" (the match arm calling
check_expression with DiagnosticKind::BaseToString) to use a check that only
considers an actual custom toString member rather than
has_custom_stringification_member() (which conflates valueOf). Either add a new
helper like has_custom_to_string_member() that looks for an explicit
toString/toLocaleString definition or change the existing helper to accept a
flag for direct-call semantics, and replace uses at the shown match (and the
other occurrences around lines ~487–495 and ~750–756) so direct calls are only
considered safe when a true custom toString/toLocaleString exists.
| /// Combine the certainties of intersection constituents. If any constituent is `Always`, the result is `Always`. Otherwise, the result is `Never`. | ||
| fn combine_intersection(certainties: impl Iterator<Item = Usefulness>) -> Usefulness { | ||
| if certainties | ||
| .into_iter() | ||
| .any(|certainty| certainty == Usefulness::Always) | ||
| { | ||
| Usefulness::Always | ||
| } else { | ||
| Usefulness::Never | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's verify the current state of the file at the specified lines
head -n 590 crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs | tail -n 25Repository: biomejs/biome
Length of output: 1010
🏁 Script executed:
# Let's look at the Usefulness enum definition
rg -A 5 "enum Usefulness" crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 116
🏁 Script executed:
# Search for other usages of combine_intersection to understand the context
rg -B 3 -A 3 "combine_intersection" crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 841
🏁 Script executed:
# Look for tests related to combine_intersection
rg -B 5 -A 10 "combine_intersection\|#\[test\]" crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs | head -n 100Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Let's also examine the combine_union function to see the pattern for handling Sometimes
rg -B 3 -A 15 "fn combine_union" crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 829
🏁 Script executed:
# Check the combine_tuple function to see how it handles Sometimes
rg -B 3 -A 15 "fn combine_tuple" crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 709
🏁 Script executed:
# Let's understand the broader context - check if there are any comments or issues about intersection handling
rg -B 10 -A 20 "AggregateKind::Intersection" crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs | head -n 60Repository: biomejs/biome
Length of output: 2276
🏁 Script executed:
# Check git history to see when this function was introduced or modified
git log --oneline -n 20 -- crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 76
🏁 Script executed:
# Search for any related issues or discussions mentioning intersection or usefulness
rg "intersection|Usefulness" crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs | head -n 30Repository: biomejs/biome
Length of output: 1800
🏁 Script executed:
# Let's check the actual semantics by looking at how Usefulness is used in diagnostics
rg -B 5 -A 10 "Usefulness::Sometimes\|Usefulness::Never" crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs | head -n 80Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Let's verify the proposed fix doesn't break any existing tests
fd "no_base_to_string" crates/biome_js_analyze/tests --type fRepository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Search for test files related to no_base_to_string
fd -i "no_base_to_string" tests/Repository: biomejs/biome
Length of output: 151
🏁 Script executed:
# Also check if there are snapshot tests for this rule
find tests -type d -name "*base*to*string*" -o -type d -name "*nursery*" | head -20Repository: biomejs/biome
Length of output: 98
🏁 Script executed:
# Let's look at the actual code context more broadly to understand intersection semantics
cat -n crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs | sed -n '550,650p'Repository: biomejs/biome
Length of output: 3927
🏁 Script executed:
# Search for test specs directory structure
find . -type d -name "specs" -o -type d -name "nursery" 2>/dev/null | head -20Repository: biomejs/biome
Length of output: 928
🏁 Script executed:
# Look for snapshot test files
find . -name "*.snap" -path "*no_base_to_string*" 2>/dev/null | head -10Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Check the broader repository structure for tests
ls -la crates/biome_js_analyze/tests/specs/ 2>/dev/null | head -20Repository: biomejs/biome
Length of output: 712
🏁 Script executed:
# Look for test files for no_base_to_string rule
ls -la crates/biome_js_analyze/tests/specs/nursery/ | grep -i "base_to_string\|no_base"Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Check if there are any files in the nursery test directory
ls crates/biome_js_analyze/tests/specs/nursery/ | grep -i baseRepository: biomejs/biome
Length of output: 72
🏁 Script executed:
# Let's find all test files related to this rule
find crates/biome_js_analyze/tests -name "*no_base_to_string*"Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Let's explore the noBaseToString test directory
ls -la crates/biome_js_analyze/tests/specs/nursery/noBaseToString/Repository: biomejs/biome
Length of output: 670
🏁 Script executed:
# Read the test files to understand what cases are covered
find crates/biome_js_analyze/tests/specs/nursery/noBaseToString/ -type f | head -20Repository: biomejs/biome
Length of output: 610
🏁 Script executed:
# Let's read the invalid test cases to understand intersection type testing
cat crates/biome_js_analyze/tests/specs/nursery/noBaseToString/invalid.tsRepository: biomejs/biome
Length of output: 603
🏁 Script executed:
# Read the snapshot to see expected diagnostics
cat crates/biome_js_analyze/tests/specs/nursery/noBaseToString/invalid.ts.snap | head -100Repository: biomejs/biome
Length of output: 2869
🏁 Script executed:
# Let's understand the semantics better by looking at how Usefulness values are used in the rule
rg -B 10 "Usefulness::Sometimes\|Usefulness::Never\|Usefulness::Always" crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs | head -150Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Check if there are any comments explaining intersection semantics
rg -B 5 -A 5 "intersection\|Intersection" crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs | head -100Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Let's understand the semantics better by examining how the rule makes decisions
rg -B 20 "fn collect_certainty" crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs | head -50Repository: biomejs/biome
Length of output: 705
🏁 Script executed:
# Check what Usefulness values mean by looking at where diagnostics are emitted
rg -B 5 "emit_diagnostic\|Usefulness" crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs | grep -A 3 -B 3 "Usefulness::"Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Let's look at the diagnostic emission logic to understand what Usefulness means
cat -n crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs | sed -n '470,510p'Repository: biomejs/biome
Length of output: 1967
🏁 Script executed:
# Let's trace through a specific example to understand the semantics
# Look at how the rule determines whether to emit a diagnostic
rg -B 10 -A 5 "RuleState\|if certainty" crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs | head -40Repository: biomejs/biome
Length of output: 39
🏁 Script executed:
# Let's verify the semantics by checking when diagnostics are actually emitted
cat -n crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs | sed -n '410,445p'Repository: biomejs/biome
Length of output: 1591
🏁 Script executed:
# Let's also check the full context around the emit logic
cat -n crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs | sed -n '395,430p'Repository: biomejs/biome
Length of output: 1786
🏁 Script executed:
# Let's look at the end of the file to see the full diagnostic emission logic
cat -n crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs | sed -n '350,380p'Repository: biomejs/biome
Length of output: 1104
🏁 Script executed:
# Let's check the rule implementation entry point
rg -B 5 -A 15 "impl Rule for NoBaseToString" crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rsRepository: biomejs/biome
Length of output: 844
Preserve Sometimes through intersections.
When analysing an intersection like (A | B) & C, a child can be Sometimes (uncertain). The current implementation collapses all non-Always cases to Never, losing this uncertainty and making the rule overstate certainty. With Sometimes collapsed away, (A | B) & C can emit a definite diagnostic when only one branch is actually problematic.
Proposed fix
fn combine_intersection(certainties: impl Iterator<Item = Usefulness>) -> Usefulness {
- if certainties
- .into_iter()
- .any(|certainty| certainty == Usefulness::Always)
- {
- Usefulness::Always
- } else {
- Usefulness::Never
- }
+ let mut saw_sometimes = false;
+
+ for certainty in certainties {
+ match certainty {
+ Usefulness::Always => return Usefulness::Always,
+ Usefulness::Sometimes => saw_sometimes = true,
+ Usefulness::Never => {}
+ }
+ }
+
+ if saw_sometimes {
+ Usefulness::Sometimes
+ } else {
+ Usefulness::Never
+ }
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /// Combine the certainties of intersection constituents. If any constituent is `Always`, the result is `Always`. Otherwise, the result is `Never`. | |
| fn combine_intersection(certainties: impl Iterator<Item = Usefulness>) -> Usefulness { | |
| if certainties | |
| .into_iter() | |
| .any(|certainty| certainty == Usefulness::Always) | |
| { | |
| Usefulness::Always | |
| } else { | |
| Usefulness::Never | |
| } | |
| /// Combine the certainties of intersection constituents. If any constituent is `Always`, the result is `Always`. Otherwise, the result is `Never`. | |
| fn combine_intersection(certainties: impl Iterator<Item = Usefulness>) -> Usefulness { | |
| let mut saw_sometimes = false; | |
| for certainty in certainties { | |
| match certainty { | |
| Usefulness::Always => return Usefulness::Always, | |
| Usefulness::Sometimes => saw_sometimes = true, | |
| Usefulness::Never => {} | |
| } | |
| } | |
| if saw_sometimes { | |
| Usefulness::Sometimes | |
| } else { | |
| Usefulness::Never | |
| } | |
| } |
🤖 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_base_to_string.rs` around lines
579 - 588, The combine_intersection function currently collapses any non-Always
certainty to Never and thus loses Sometimes; update combine_intersection so it
first returns Usefulness::Always if any constituent is Always, otherwise returns
Usefulness::Sometimes if any constituent is Sometimes, and only returns
Usefulness::Never when all constituents are Never; update the iterator checks in
combine_intersection to test for Always first, then for Sometimes (e.g., using
any on the iterator or by collecting into a small temp vector/iterator clone) so
that Sometimes is preserved through intersections.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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_base_to_string.rs`:
- Around line 697-707: The RegExp branch in the TypeData::Literal match is
incorrectly marking RegExp as using the base Object toString (setting saw_true);
update the Literal::RegExp(_) arm to indicate it does NOT use the base Object
stringification (e.g., return Some(false) or otherwise avoid setting saw_true)
so RegExp is treated like a type with a custom toString; adjust the
Literal::RegExp(_) match arm in no_base_to_string.rs (inside the
TypeData::Literal match) and ensure tests and DEFAULT_IGNORED_TYPE_NAMES
handling remain consistent.
🪄 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: c21798cc-1825-4dae-9363-6e880efe16d1
📒 Files selected for processing (2)
crates/biome_cli/src/execute/migrate/eslint_typescript.rscrates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs
🚧 Files skipped from review as they are similar to previous changes (1)
- crates/biome_cli/src/execute/migrate/eslint_typescript.rs
Would you mind explaining the logic of the PR in the description? Wouldn't be able to review it if you don't prepare us |
a5aa0f9 to
3e5502b
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
.changeset/tidy-lamps-bake.md (1)
5-5: ⚡ Quick winShow one tiny example in the changeset.
For new rules we usually include a concrete snippet so the release notes are scannable at a glance. A short inline example like
String({})or`${value}`would do nicely.As per coding guidelines, "changeset descriptions should focus on user-facing changes only; internal refactoring without user-visible behavior changes does not require a changeset" and "include examples with inline code snippets or code blocks for new rules".Possible tweak
-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. +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, such as `String({})` or `` `${value}` ``. The rule also supports the `ignoredTypeNames` option.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.changeset/tidy-lamps-bake.md at line 5, Add a tiny inline example showing the rule in action: mention the new linter rule noBaseToString and append a short snippet like String({}) or `${value}` to demonstrate the reported behavior; also note the supported option ignoredTypeNames so readers see usage at a glance (e.g., "reports when String({}) or `${value}` yields '[object Object]'; supports ignoredTypeNames"). Ensure the example is concise and appears in the changeset description text.crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs (1)
21-70: ⚡ Quick winAdd an options section for
ignoredTypeNames.The rule exposes an option, but the doc block does not yet state the default, show the JSON shape, or include a
use_optionsexample. That tends to leave the generated docs a bit skinny for users.As per coding guidelines, "Rule documentation for options must include a default value statement, a JSON options block, and a code example with the expect_diagnostic or use_options directive".Suggested doc skeleton
/// `${new CustomToString()}`; /// ``` + /// + /// ## Options + /// + /// The default value of `ignoredTypeNames` is `["Error", "RegExp", "URL", "URLSearchParams"]`. + /// + /// ```json + /// { + /// "linter": { + /// "rules": { + /// "nursery": { + /// "noBaseToString": { + /// "options": { + /// "ignoredTypeNames": ["Error"] + /// } + /// } + /// } + /// } + /// } + /// } + /// ``` + /// + /// ```ts,use_options + /// const value: Error = new Error("boom"); + /// String(value); + /// ``` pub NoBaseToString {🤖 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_base_to_string.rs` around lines 21 - 70, The doc comment for the NoBaseToString rule is missing an Options section describing the ignoredTypeNames option; update the doc block above pub NoBaseToString to add an "## Options" subsection that states the default value ignoredTypeNames = ["Error", "RegExp", "URL", "URLSearchParams"], include a JSON example showing the rule config shape (with "options": { "ignoredTypeNames": ["Error"] }), and add a TypeScript example using the use_options directive (e.g., const value: Error = new Error("boom"); String(value);) so the generated docs include the default, JSON options block, and a code example as required by the guidelines.
🤖 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_base_to_string.rs`:
- Around line 522-529: The safety check incorrectly treats toLocaleString as
proof of custom stringification; update has_custom_stringification_member (and
callers like is_to_string_like_from_object and the AnalysisMode::ToString match)
to only consider toString and valueOf as valid custom stringification members
for String(x)/`${x}` coercion and ignore toLocaleString entirely, so objects
with only toLocaleString no longer count as safe and will fall through to
Usefulness::Always where appropriate.
---
Nitpick comments:
In @.changeset/tidy-lamps-bake.md:
- Line 5: Add a tiny inline example showing the rule in action: mention the new
linter rule noBaseToString and append a short snippet like String({}) or
`${value}` to demonstrate the reported behavior; also note the supported option
ignoredTypeNames so readers see usage at a glance (e.g., "reports when
String({}) or `${value}` yields '[object Object]'; supports ignoredTypeNames").
Ensure the example is concise and appears in the changeset description text.
In `@crates/biome_js_analyze/src/lint/nursery/no_base_to_string.rs`:
- Around line 21-70: The doc comment for the NoBaseToString rule is missing an
Options section describing the ignoredTypeNames option; update the doc block
above pub NoBaseToString to add an "## Options" subsection that states the
default value ignoredTypeNames = ["Error", "RegExp", "URL", "URLSearchParams"],
include a JSON example showing the rule config shape (with "options": {
"ignoredTypeNames": ["Error"] }), and add a TypeScript example using the
use_options directive (e.g., const value: Error = new Error("boom");
String(value);) so the generated docs include the default, JSON options block,
and a code example as required by the guidelines.
🪄 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: d24bca95-05f4-4a3f-8dc8-ab36e5b2358a
⛔ Files ignored due to path filters (1)
crates/biome_js_analyze/tests/specs/nursery/noBaseToString/invalid.ts.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (4)
.changeset/tidy-lamps-bake.mdcrates/biome_js_analyze/src/lint/nursery/no_base_to_string.rscrates/biome_module_graph/src/js_module_info/collector.rscrates/biome_module_graph/tests/spec_tests.rs
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
Summary
This PR adds noBaseToString which is a port of https://typescript-eslint.io/rules/no-base-to-string/
Generated by gpt 5.4
ngl, this one sucks. It's very complicated.
The goal of this rule is to prevent accidentally rendering
[object Object]in a string.As psuedo code, the rule is essentially:
So a lot of the code is mostly dealing with evaluating type info.
AnalysisModehas two cases:ToString: used forString(x),x.toString(), template interpolation, string concatenation.Join: used forarray.join(",").The distinction matters because
join()stringifies the elements, not the object itself.collect_certainty()collect_certainty()is pretty much the core business logic of the rule. It determines a type'sUsefulness, which is a label of how useful the type text is if you call.toString()on it. If we can't resolve a type, we bail to avoid raising false positives.collect_certainty()uses a stack ofAnalysisTasks. The agent's summary:Eval(type, mode)means “analyze this type”Aggregate(kind, count)means “combine the nextcountchild results”Leave(key)means “we’re done exploring this type, remove it from the active cycle set”Those task types are defined at
:172-183.That function handles types in this order:
:397-410).Always(:415-420,:600-633).Always(:415-420,:755-911).:423-431,:557-569).:439-453,:571-580).:456-470,:582-598).:473-477,:539-555).ToStringmode, ask: “does this ultimately behave like plainObject.prototype.toString?” (:480-487,:635-737).How unions, intersections, and tuples are handled is explained in doc comments.
How It Detects “Plain Object Stringification”
is_to_string_like_from_object()essentially checks: will this use the default object stringification? or does it implement a custom.toString()or similar to avoid that?Test Plan
snapshots
Docs