From b24b44c34b2912ed02653b43c96f807579e6a3aa Mon Sep 17 00:00:00 2001 From: Victorien Elvinger Date: Thu, 25 Apr 2024 11:40:45 +0200 Subject: [PATCH] fix(lint/useConst): handle reads before assignment and improve docs (#2584) --- CHANGELOG.md | 26 +- ..._runs_linter_not_formatter_issue_3495.snap | 4 +- ...handles_ignored_and_not_ignored_files.snap | 4 +- .../include_files_in_subdir.snap | 4 +- .../include_files_in_symlinked_subdir.snap | 4 +- .../biome_configuration/src/linter/rules.rs | 2 +- .../src/lint/style/use_const.rs | 80 ++++- .../specs/style/useConst/invalid.jsonc.snap | 296 +++++++++--------- .../tests/specs/style/useConst/valid.jsonc | 7 +- .../specs/style/useConst/valid.jsonc.snap | 13 + justfile | 2 +- .../@biomejs/backend-jsonrpc/src/workspace.ts | 2 +- .../@biomejs/biome/configuration_schema.json | 2 +- 13 files changed, 263 insertions(+), 183 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 713e7bd8e93e..10770333b5b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,14 +24,14 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b ```diff import "z" - - import { D } from "d"; + - import { D } from "d"; import { C } from "c"; - + import { D } from "d"; + + import { D } from "d"; import "y" import "x" - - import { B } from "b"; + - import { B } from "b"; import { A } from "a"; - + import { B } from "b"; + + import { B } from "b"; import "w" ``` @@ -47,6 +47,8 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b This causes `biome migrate eslint` to fail or ignore them. These edge cases are now handled correctly. + Contributed by @Conaclos + ### Configuration ### Editors @@ -61,6 +63,22 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b ### Linter +#### Bug fixes + +- [useConst](https://biomejs.dev/linter/rules/use-const/) now ignores a variable that is read before its assignment. + + Previously, the rule reported the following example: + + ```js + let x; + x; // read + x = 0; // write + ``` + + It is now correctly ignored. + + Contributed by @Conaclos + ### Parser ## 1.7.1 (2024-04-22) diff --git a/crates/biome_cli/tests/snapshots/main_commands_ci/ci_runs_linter_not_formatter_issue_3495.snap b/crates/biome_cli/tests/snapshots/main_commands_ci/ci_runs_linter_not_formatter_issue_3495.snap index 81cdbdc37f0a..b82d78417484 100644 --- a/crates/biome_cli/tests/snapshots/main_commands_ci/ci_runs_linter_not_formatter_issue_3495.snap +++ b/crates/biome_cli/tests/snapshots/main_commands_ci/ci_runs_linter_not_formatter_issue_3495.snap @@ -34,12 +34,12 @@ ci ━━━━━━━━━━━━━━━━━━━━━━━━━ ```block file.js:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - × This let declares a variable which is never re-assigned. + × This let declares a variable that is only assigned once. > 1 │ let a = !b || !c │ ^^^ - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ let a = !b || !c │ ^ diff --git a/crates/biome_cli/tests/snapshots/main_commands_ci/correctly_handles_ignored_and_not_ignored_files.snap b/crates/biome_cli/tests/snapshots/main_commands_ci/correctly_handles_ignored_and_not_ignored_files.snap index a3e2dea26445..b4a30793ce53 100644 --- a/crates/biome_cli/tests/snapshots/main_commands_ci/correctly_handles_ignored_and_not_ignored_files.snap +++ b/crates/biome_cli/tests/snapshots/main_commands_ci/correctly_handles_ignored_and_not_ignored_files.snap @@ -52,12 +52,12 @@ ci ━━━━━━━━━━━━━━━━━━━━━━━━━ ```block /formatter-ignored/test.js:1:19 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - × This let declares a variable which is never re-assigned. + × This let declares a variable that is only assigned once. > 1 │ statement( ) ; let a = !b || !c; │ ^^^ - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ statement( ) ; let a = !b || !c; │ ^ diff --git a/crates/biome_cli/tests/snapshots/main_commands_lint/include_files_in_subdir.snap b/crates/biome_cli/tests/snapshots/main_commands_lint/include_files_in_subdir.snap index 85c96af1d731..de0ddf78ea21 100644 --- a/crates/biome_cli/tests/snapshots/main_commands_lint/include_files_in_subdir.snap +++ b/crates/biome_cli/tests/snapshots/main_commands_lint/include_files_in_subdir.snap @@ -39,14 +39,14 @@ lint ━━━━━━━━━━━━━━━━━━━━━━━━━ ```block /include_files_in_subdir/subdir/file.js:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━ - × This let declares a variable which is never re-assigned. + × This let declares a variable that is only assigned once. > 1 │ let a = 4; │ ^^^ 2 │ debugger; 3 │ console.log(a); - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ let a = 4; │ ^ diff --git a/crates/biome_cli/tests/snapshots/main_commands_lint/include_files_in_symlinked_subdir.snap b/crates/biome_cli/tests/snapshots/main_commands_lint/include_files_in_symlinked_subdir.snap index 276908e62827..aa771ccbc90e 100644 --- a/crates/biome_cli/tests/snapshots/main_commands_lint/include_files_in_symlinked_subdir.snap +++ b/crates/biome_cli/tests/snapshots/main_commands_lint/include_files_in_symlinked_subdir.snap @@ -39,14 +39,14 @@ lint ━━━━━━━━━━━━━━━━━━━━━━━━━ ```block /include_files_in_symlinked_subdir/symlinked/file.js:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━ - × This let declares a variable which is never re-assigned. + × This let declares a variable that is only assigned once. > 1 │ let a = 4; │ ^^^ 2 │ debugger; 3 │ console.log(a); - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ let a = 4; │ ^ diff --git a/crates/biome_configuration/src/linter/rules.rs b/crates/biome_configuration/src/linter/rules.rs index 52b54d422436..2de1341aacf0 100644 --- a/crates/biome_configuration/src/linter/rules.rs +++ b/crates/biome_configuration/src/linter/rules.rs @@ -3556,7 +3556,7 @@ pub struct Style { #[doc = "Require consistently using either T\\[] or Array\\"] #[serde(skip_serializing_if = "Option::is_none")] pub use_consistent_array_type: Option>, - #[doc = "Require const declarations for variables that are never reassigned after declared."] + #[doc = "Require const declarations for variables that are only assigned once."] #[serde(skip_serializing_if = "Option::is_none")] pub use_const: Option>, #[doc = "Enforce default function parameters and optional function parameters to be last."] diff --git a/crates/biome_js_analyze/src/lint/style/use_const.rs b/crates/biome_js_analyze/src/lint/style/use_const.rs index 1396093a75e8..2055b1955b97 100644 --- a/crates/biome_js_analyze/src/lint/style/use_const.rs +++ b/crates/biome_js_analyze/src/lint/style/use_const.rs @@ -1,4 +1,7 @@ -use crate::{services::semantic::Semantic, JsRuleAction}; +use crate::{ + services::{control_flow::AnyJsControlFlowRoot, semantic::Semantic}, + JsRuleAction, +}; use biome_analyze::{ context::RuleContext, declare_rule, ActionCategory, FixKind, Rule, RuleDiagnostic, RuleSource, }; @@ -11,7 +14,10 @@ use biome_js_syntax::*; use biome_rowan::{declare_node_union, AstNode, BatchMutationExt}; declare_rule! { - /// Require `const` declarations for variables that are never reassigned after declared. + /// Require `const` declarations for variables that are only assigned once. + /// + /// Variables that are initialized and never reassigned and + /// variables that are only assigned once can be declared as `const`. /// /// ## Examples /// @@ -37,6 +43,11 @@ declare_rule! { /// ``` /// /// ```js,expect_diagnostic + /// let a; + /// a = 0; + /// ``` + /// + /// ```js,expect_diagnostic /// let a = 3; /// { /// let a = 4; @@ -56,6 +67,12 @@ declare_rule! { /// let a = 1, b = 2; /// b = 3; /// ``` + /// + /// ```js + /// let a; + /// a; // the variable is read before its assignement + /// a = 0; + /// ``` pub UseConst { version: "1.0.0", name: "useConst", @@ -87,9 +104,9 @@ impl Rule for UseConst { let declaration = ctx.query(); let kind = declaration.kind_token().ok()?; let title_end = if state.can_be_const.len() == 1 { - "a variable which is never re-assigned." + "a variable that is only assigned once." } else { - "some variables which are never re-assigned." + "some variables that are only assigned once." }; let mut diag = RuleDiagnostic::new( rule_category!(), @@ -100,13 +117,22 @@ impl Rule for UseConst { ); for binding in state.can_be_const.iter() { - let binding = binding.name_token().ok()?; - diag = diag.detail( - binding.text_trimmed_range(), - markup! { - "'"{ binding.text_trimmed() }"' is never re-assigned." - }, - ); + let binding_name = binding.name_token().ok()?; + if let Some(write) = binding.all_writes(ctx.model()).next() { + diag = diag.detail( + write.syntax().text_trimmed_range(), + markup! { + "'"{ binding_name.text_trimmed() }"' is only assigned here." + }, + ); + } else { + diag = diag.detail( + binding_name.text_trimmed_range(), + markup! { + "'"{ binding_name.text_trimmed() }"' is never reassigned." + }, + ); + } } Some(diag) @@ -188,12 +214,12 @@ fn check_binding_can_be_const( return writes.next().is_none().then_some(ConstCheckResult::Fix); } - // If no initializer and one assignment in same scope - let write = match (writes.next(), writes.next()) { - (Some(v), None) if v.scope() == binding.scope(model) => v, - _ => return None, - }; - + let binding_scope = binding.scope(model); + let write = writes.next()?; + // If teher are multiple assignement or the write is not in the same scope + if writes.next().is_some() || write.scope() != binding_scope { + return None; + } let host = write .syntax() .ancestors() @@ -202,6 +228,26 @@ fn check_binding_can_be_const( return None; } + let mut refs = binding.all_references(model); + // If a read precedes the write, don't report it. + // Ignore reads that are in an inner control flow root. + // For example, this ignores reads inside a function: + // ```js + // let v; + // function f() { v; } + // ``` + let next_ref = refs.find(|x| { + x.is_write() + || !x + .scope() + .ancestors() + .take_while(|scope| scope != &binding_scope) + .any(|scope| AnyJsControlFlowRoot::can_cast(scope.syntax().kind())) + }); + if matches!(next_ref, Some(next_ref) if next_ref.is_read()) { + return None; + } + host.can_become_variable_declaration()? .then_some(ConstCheckResult::Report) } diff --git a/crates/biome_js_analyze/tests/specs/style/useConst/invalid.jsonc.snap b/crates/biome_js_analyze/tests/specs/style/useConst/invalid.jsonc.snap index 6c81ca399176..11c45122c48b 100644 --- a/crates/biome_js_analyze/tests/specs/style/useConst/invalid.jsonc.snap +++ b/crates/biome_js_analyze/tests/specs/style/useConst/invalid.jsonc.snap @@ -11,12 +11,12 @@ let x = 1; foo(x); ``` invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ let x = 1; foo(x); │ ^^^ - i 'x' is never re-assigned. + i 'x' is never reassigned. > 1 │ let x = 1; foo(x); │ ^ @@ -38,12 +38,12 @@ for (let i in [1,2,3]) { foo(i); } ``` invalid.jsonc:1:6 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ for (let i in [1,2,3]) { foo(i); } │ ^^^ - i 'i' is never re-assigned. + i 'i' is never reassigned. > 1 │ for (let i in [1,2,3]) { foo(i); } │ ^ @@ -65,12 +65,12 @@ for (let x of [1,2,3]) { foo(x); } ``` invalid.jsonc:1:6 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ for (let x of [1,2,3]) { foo(x); } │ ^^^ - i 'x' is never re-assigned. + i 'x' is never reassigned. > 1 │ for (let x of [1,2,3]) { foo(x); } │ ^ @@ -92,12 +92,12 @@ invalid.jsonc:1:6 lint/style/useConst FIXABLE ━━━━━━━━━━ ``` invalid.jsonc:1:15 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ (function() { let x = 1; foo(x); })(); │ ^^^ - i 'x' is never re-assigned. + i 'x' is never reassigned. > 1 │ (function() { let x = 1; foo(x); })(); │ ^ @@ -119,12 +119,12 @@ invalid.jsonc:1:15 lint/style/useConst FIXABLE ━━━━━━━━━━ ``` invalid.jsonc:1:20 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ (function() { for (let i in [1,2,3]) { foo(i); } })(); │ ^^^ - i 'i' is never re-assigned. + i 'i' is never reassigned. > 1 │ (function() { for (let i in [1,2,3]) { foo(i); } })(); │ ^ @@ -146,12 +146,12 @@ invalid.jsonc:1:20 lint/style/useConst FIXABLE ━━━━━━━━━━ ``` invalid.jsonc:1:20 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ (function() { for (let x of [1,2,3]) { foo(x); } })(); │ ^^^ - i 'x' is never re-assigned. + i 'x' is never reassigned. > 1 │ (function() { for (let x of [1,2,3]) { foo(x); } })(); │ ^ @@ -173,12 +173,12 @@ let f = (function() { let g = x; })(); f = 1; ``` invalid.jsonc:1:23 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ let f = (function() { let g = x; })(); f = 1; │ ^^^ - i 'g' is never re-assigned. + i 'g' is never reassigned. > 1 │ let f = (function() { let g = x; })(); f = 1; │ ^ @@ -200,12 +200,12 @@ let x = 0; { let x = 1; foo(x); } x = 0; ``` invalid.jsonc:1:14 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ let x = 0; { let x = 1; foo(x); } x = 0; │ ^^^ - i 'x' is never re-assigned. + i 'x' is never reassigned. > 1 │ let x = 0; { let x = 1; foo(x); } x = 0; │ ^ @@ -227,12 +227,12 @@ for (let i = 0; i < 10; ++i) { let x = 1; foo(x); } ``` invalid.jsonc:1:32 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ for (let i = 0; i < 10; ++i) { let x = 1; foo(x); } │ ^^^ - i 'x' is never re-assigned. + i 'x' is never reassigned. > 1 │ for (let i = 0; i < 10; ++i) { let x = 1; foo(x); } │ ^ @@ -254,12 +254,12 @@ for (let i in [1,2,3]) { let x = 1; foo(x); } ``` invalid.jsonc:1:6 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ for (let i in [1,2,3]) { let x = 1; foo(x); } │ ^^^ - i 'i' is never re-assigned. + i 'i' is never reassigned. > 1 │ for (let i in [1,2,3]) { let x = 1; foo(x); } │ ^ @@ -275,12 +275,12 @@ invalid.jsonc:1:6 lint/style/useConst FIXABLE ━━━━━━━━━━ ``` invalid.jsonc:1:26 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ for (let i in [1,2,3]) { let x = 1; foo(x); } │ ^^^ - i 'x' is never re-assigned. + i 'x' is never reassigned. > 1 │ for (let i in [1,2,3]) { let x = 1; foo(x); } │ ^ @@ -302,15 +302,15 @@ var foo = function() { for (const b of c) { let a; a = 1; } }; ``` invalid.jsonc:1:45 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ var foo = function() { for (const b of c) { let a; a = 1; } }; │ ^^^ - i 'a' is never re-assigned. + i 'a' is only assigned here. > 1 │ var foo = function() { for (const b of c) { let a; a = 1; } }; - │ ^ + │ ^ ``` @@ -324,15 +324,15 @@ var foo = function() { for (const b of c) { let a; ({a} = 1); } }; ``` invalid.jsonc:1:45 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ var foo = function() { for (const b of c) { let a; ({a} = 1); } }; │ ^^^ - i 'a' is never re-assigned. + i 'a' is only assigned here. > 1 │ var foo = function() { for (const b of c) { let a; ({a} = 1); } }; - │ ^ + │ ^ ``` @@ -346,15 +346,15 @@ let x; x = 0; ``` invalid.jsonc:1:1 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ let x; x = 0; │ ^^^ - i 'x' is never re-assigned. + i 'x' is only assigned here. > 1 │ let x; x = 0; - │ ^ + │ ^ ``` @@ -368,15 +368,15 @@ switch (a) { case 0: let x; x = 0; } ``` invalid.jsonc:1:22 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ switch (a) { case 0: let x; x = 0; } │ ^^^ - i 'x' is never re-assigned. + i 'x' is only assigned here. > 1 │ switch (a) { case 0: let x; x = 0; } - │ ^ + │ ^ ``` @@ -390,15 +390,15 @@ invalid.jsonc:1:22 lint/style/useConst ━━━━━━━━━━━━━ ``` invalid.jsonc:1:15 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ (function() { let x; x = 1; })(); │ ^^^ - i 'x' is never re-assigned. + i 'x' is only assigned here. > 1 │ (function() { let x; x = 1; })(); - │ ^ + │ ^ ``` @@ -412,17 +412,17 @@ let {a: {b, c}} = {a: {b: 1, c: 2}} ``` invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares some variables which are never re-assigned. + ! This let declares some variables that are only assigned once. > 1 │ let {a: {b, c}} = {a: {b: 1, c: 2}} │ ^^^ - i 'b' is never re-assigned. + i 'b' is never reassigned. > 1 │ let {a: {b, c}} = {a: {b: 1, c: 2}} │ ^ - i 'c' is never re-assigned. + i 'c' is never reassigned. > 1 │ let {a: {b, c}} = {a: {b: 1, c: 2}} │ ^ @@ -444,17 +444,17 @@ let {a = 0, b} = obj; foo(a, b); ``` invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares some variables which are never re-assigned. + ! This let declares some variables that are only assigned once. > 1 │ let {a = 0, b} = obj; foo(a, b); │ ^^^ - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ let {a = 0, b} = obj; foo(a, b); │ ^ - i 'b' is never re-assigned. + i 'b' is never reassigned. > 1 │ let {a = 0, b} = obj; foo(a, b); │ ^ @@ -476,12 +476,12 @@ let [a] = [1] ``` invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ let [a] = [1] │ ^^^ - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ let [a] = [1] │ ^ @@ -503,12 +503,12 @@ let {a} = obj ``` invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ let {a} = obj │ ^^^ - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ let {a} = obj │ ^ @@ -530,20 +530,20 @@ let a, b; ({a = 0, b} = obj); foo(a, b); ``` invalid.jsonc:1:1 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares some variables which are never re-assigned. + ! This let declares some variables that are only assigned once. > 1 │ let a, b; ({a = 0, b} = obj); foo(a, b); │ ^^^ - i 'a' is never re-assigned. + i 'a' is only assigned here. > 1 │ let a, b; ({a = 0, b} = obj); foo(a, b); - │ ^ + │ ^ - i 'b' is never re-assigned. + i 'b' is only assigned here. > 1 │ let a, b; ({a = 0, b} = obj); foo(a, b); - │ ^ + │ ^ ``` @@ -557,15 +557,15 @@ let x; function foo() { bar(x); } x = 0; ``` invalid.jsonc:1:1 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ let x; function foo() { bar(x); } x = 0; │ ^^^ - i 'x' is never re-assigned. + i 'x' is only assigned here. > 1 │ let x; function foo() { bar(x); } x = 0; - │ ^ + │ ^ ``` @@ -579,12 +579,12 @@ invalid.jsonc:1:1 lint/style/useConst ━━━━━━━━━━━━━━ ``` invalid.jsonc:1:24 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ /*eslint use-x:error*/ let x = 1 │ ^^^ - i 'x' is never re-assigned. + i 'x' is never reassigned. > 1 │ /*eslint use-x:error*/ let x = 1 │ ^ @@ -606,12 +606,12 @@ invalid.jsonc:1:24 lint/style/useConst FIXABLE ━━━━━━━━━━ ``` invalid.jsonc:1:26 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ /*eslint use-x:error*/ { let x = 1 } │ ^^^ - i 'x' is never re-assigned. + i 'x' is never reassigned. > 1 │ /*eslint use-x:error*/ { let x = 1 } │ ^ @@ -633,17 +633,17 @@ let { foo, bar } = baz; ``` invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares some variables which are never re-assigned. + ! This let declares some variables that are only assigned once. > 1 │ let { foo, bar } = baz; │ ^^^ - i 'foo' is never re-assigned. + i 'foo' is never reassigned. > 1 │ let { foo, bar } = baz; │ ^^^ - i 'bar' is never re-assigned. + i 'bar' is never reassigned. > 1 │ let { foo, bar } = baz; │ ^^^ @@ -665,12 +665,12 @@ const x = [1,2]; let [,y] = x; ``` invalid.jsonc:1:18 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ const x = [1,2]; let [,y] = x; │ ^^^ - i 'y' is never re-assigned. + i 'y' is never reassigned. > 1 │ const x = [1,2]; let [,y] = x; │ ^ @@ -692,17 +692,17 @@ const x = [1,2,3]; let [y,,z] = x; ``` invalid.jsonc:1:20 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares some variables which are never re-assigned. + ! This let declares some variables that are only assigned once. > 1 │ const x = [1,2,3]; let [y,,z] = x; │ ^^^ - i 'y' is never re-assigned. + i 'y' is never reassigned. > 1 │ const x = [1,2,3]; let [y,,z] = x; │ ^ - i 'z' is never re-assigned. + i 'z' is never reassigned. > 1 │ const x = [1,2,3]; let [y,,z] = x; │ ^ @@ -724,15 +724,15 @@ let predicate; [, {foo:returnType, predicate}] = foo(); ``` invalid.jsonc:1:1 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ let predicate; [, {foo:returnType, predicate}] = foo(); │ ^^^ - i 'predicate' is never re-assigned. + i 'predicate' is only assigned here. > 1 │ let predicate; [, {foo:returnType, predicate}] = foo(); - │ ^^^^^^^^^ + │ ^^^^^^^^^ ``` @@ -746,15 +746,15 @@ let predicate; [, {foo:returnType, predicate}, ...bar ] = foo(); ``` invalid.jsonc:1:1 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ let predicate; [, {foo:returnType, predicate}, ...bar ] = foo(); │ ^^^ - i 'predicate' is never re-assigned. + i 'predicate' is only assigned here. > 1 │ let predicate; [, {foo:returnType, predicate}, ...bar ] = foo(); - │ ^^^^^^^^^ + │ ^^^^^^^^^ ``` @@ -768,15 +768,15 @@ let predicate; [, {foo:returnType, ...predicate} ] = foo(); ``` invalid.jsonc:1:1 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ let predicate; [, {foo:returnType, ...predicate} ] = foo(); │ ^^^ - i 'predicate' is never re-assigned. + i 'predicate' is only assigned here. > 1 │ let predicate; [, {foo:returnType, ...predicate} ] = foo(); - │ ^^^^^^^^^ + │ ^^^^^^^^^ ``` @@ -790,17 +790,17 @@ let x = 'x', y = 'y'; ``` invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares some variables which are never re-assigned. + ! This let declares some variables that are only assigned once. > 1 │ let x = 'x', y = 'y'; │ ^^^ - i 'x' is never re-assigned. + i 'x' is never reassigned. > 1 │ let x = 'x', y = 'y'; │ ^ - i 'y' is never re-assigned. + i 'y' is never reassigned. > 1 │ let x = 'x', y = 'y'; │ ^ @@ -822,17 +822,17 @@ let x = 1, y = 'y'; let z = 1; ``` invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares some variables which are never re-assigned. + ! This let declares some variables that are only assigned once. > 1 │ let x = 1, y = 'y'; let z = 1; │ ^^^ - i 'x' is never re-assigned. + i 'x' is never reassigned. > 1 │ let x = 1, y = 'y'; let z = 1; │ ^ - i 'y' is never re-assigned. + i 'y' is never reassigned. > 1 │ let x = 1, y = 'y'; let z = 1; │ ^ @@ -848,12 +848,12 @@ invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━ ``` invalid.jsonc:1:21 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ let x = 1, y = 'y'; let z = 1; │ ^^^ - i 'z' is never re-assigned. + i 'z' is never reassigned. > 1 │ let x = 1, y = 'y'; let z = 1; │ ^ @@ -875,22 +875,22 @@ let { a, b, c} = obj; let { x, y, z} = anotherObj; x = 2; ``` invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares some variables which are never re-assigned. + ! This let declares some variables that are only assigned once. > 1 │ let { a, b, c} = obj; let { x, y, z} = anotherObj; x = 2; │ ^^^ - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ let { a, b, c} = obj; let { x, y, z} = anotherObj; x = 2; │ ^ - i 'b' is never re-assigned. + i 'b' is never reassigned. > 1 │ let { a, b, c} = obj; let { x, y, z} = anotherObj; x = 2; │ ^ - i 'c' is never re-assigned. + i 'c' is never reassigned. > 1 │ let { a, b, c} = obj; let { x, y, z} = anotherObj; x = 2; │ ^ @@ -912,17 +912,17 @@ let x = 'x', y = 'y'; function someFunc() { let a = 1, b = 2; foo(a, b) } ``` invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares some variables which are never re-assigned. + ! This let declares some variables that are only assigned once. > 1 │ let x = 'x', y = 'y'; function someFunc() { let a = 1, b = 2; foo(a, b) } │ ^^^ - i 'x' is never re-assigned. + i 'x' is never reassigned. > 1 │ let x = 'x', y = 'y'; function someFunc() { let a = 1, b = 2; foo(a, b) } │ ^ - i 'y' is never re-assigned. + i 'y' is never reassigned. > 1 │ let x = 'x', y = 'y'; function someFunc() { let a = 1, b = 2; foo(a, b) } │ ^ @@ -938,17 +938,17 @@ invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━ ``` invalid.jsonc:1:45 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares some variables which are never re-assigned. + ! This let declares some variables that are only assigned once. > 1 │ let x = 'x', y = 'y'; function someFunc() { let a = 1, b = 2; foo(a, b) } │ ^^^ - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ let x = 'x', y = 'y'; function someFunc() { let a = 1, b = 2; foo(a, b) } │ ^ - i 'b' is never re-assigned. + i 'b' is never reassigned. > 1 │ let x = 'x', y = 'y'; function someFunc() { let a = 1, b = 2; foo(a, b) } │ ^ @@ -970,12 +970,12 @@ let someFunc = () => { let a = 1, b = 2; foo(a, b) } ``` invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ let someFunc = () => { let a = 1, b = 2; foo(a, b) } │ ^^^ - i 'someFunc' is never re-assigned. + i 'someFunc' is never reassigned. > 1 │ let someFunc = () => { let a = 1, b = 2; foo(a, b) } │ ^^^^^^^^ @@ -991,17 +991,17 @@ invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━ ``` invalid.jsonc:1:24 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares some variables which are never re-assigned. + ! This let declares some variables that are only assigned once. > 1 │ let someFunc = () => { let a = 1, b = 2; foo(a, b) } │ ^^^ - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ let someFunc = () => { let a = 1, b = 2; foo(a, b) } │ ^ - i 'b' is never re-assigned. + i 'b' is never reassigned. > 1 │ let someFunc = () => { let a = 1, b = 2; foo(a, b) } │ ^ @@ -1023,12 +1023,12 @@ invalid.jsonc:1:24 lint/style/useConst FIXABLE ━━━━━━━━━━ ``` invalid.jsonc:1:32 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ /*eslint no-undef-init:error*/ let foo = undefined; │ ^^^ - i 'foo' is never re-assigned. + i 'foo' is never reassigned. > 1 │ /*eslint no-undef-init:error*/ let foo = undefined; │ ^^^ @@ -1050,12 +1050,12 @@ let a = 1; class C { static { a; } } ``` invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ let a = 1; class C { static { a; } } │ ^^^ - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ let a = 1; class C { static { a; } } │ ^ @@ -1077,12 +1077,12 @@ class C { static { a; } } let a = 1; ``` invalid.jsonc:1:27 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ class C { static { a; } } let a = 1; │ ^^^ - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ class C { static { a; } } let a = 1; │ ^ @@ -1104,12 +1104,12 @@ class C { static { let a = 1; } } ``` invalid.jsonc:1:20 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ class C { static { let a = 1; } } │ ^^^ - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ class C { static { let a = 1; } } │ ^ @@ -1131,12 +1131,12 @@ class C { static { if (foo) { let a = 1; } } } ``` invalid.jsonc:1:31 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ class C { static { if (foo) { let a = 1; } } } │ ^^^ - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ class C { static { if (foo) { let a = 1; } } } │ ^ @@ -1158,12 +1158,12 @@ class C { static { let a = 1; if (foo) { a; } } } ``` invalid.jsonc:1:20 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ class C { static { let a = 1; if (foo) { a; } } } │ ^^^ - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ class C { static { let a = 1; if (foo) { a; } } } │ ^ @@ -1185,15 +1185,15 @@ class C { static { if (foo) { let a; a = 1; } } } ``` invalid.jsonc:1:31 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ class C { static { if (foo) { let a; a = 1; } } } │ ^^^ - i 'a' is never re-assigned. + i 'a' is only assigned here. > 1 │ class C { static { if (foo) { let a; a = 1; } } } - │ ^ + │ ^ ``` @@ -1207,15 +1207,15 @@ class C { static { let a; a = 1; } } ``` invalid.jsonc:1:20 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ class C { static { let a; a = 1; } } │ ^^^ - i 'a' is never re-assigned. + i 'a' is only assigned here. > 1 │ class C { static { let a; a = 1; } } - │ ^ + │ ^ ``` @@ -1229,17 +1229,17 @@ class C { static { let { a, b } = foo; } } ``` invalid.jsonc:1:20 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares some variables which are never re-assigned. + ! This let declares some variables that are only assigned once. > 1 │ class C { static { let { a, b } = foo; } } │ ^^^ - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ class C { static { let { a, b } = foo; } } │ ^ - i 'b' is never re-assigned. + i 'b' is never reassigned. > 1 │ class C { static { let { a, b } = foo; } } │ ^ @@ -1261,20 +1261,20 @@ class C { static { let a, b; ({ a, b } = foo); } } ``` invalid.jsonc:1:20 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares some variables which are never re-assigned. + ! This let declares some variables that are only assigned once. > 1 │ class C { static { let a, b; ({ a, b } = foo); } } │ ^^^ - i 'a' is never re-assigned. + i 'a' is only assigned here. > 1 │ class C { static { let a, b; ({ a, b } = foo); } } - │ ^ + │ ^ - i 'b' is never re-assigned. + i 'b' is only assigned here. > 1 │ class C { static { let a, b; ({ a, b } = foo); } } - │ ^ + │ ^ ``` @@ -1288,15 +1288,15 @@ class C { static { let a; let b; ({ a, b } = foo); } } ``` invalid.jsonc:1:20 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ class C { static { let a; let b; ({ a, b } = foo); } } │ ^^^ - i 'a' is never re-assigned. + i 'a' is only assigned here. > 1 │ class C { static { let a; let b; ({ a, b } = foo); } } - │ ^ + │ ^ ``` @@ -1304,15 +1304,15 @@ invalid.jsonc:1:20 lint/style/useConst ━━━━━━━━━━━━━ ``` invalid.jsonc:1:27 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ class C { static { let a; let b; ({ a, b } = foo); } } │ ^^^ - i 'b' is never re-assigned. + i 'b' is only assigned here. > 1 │ class C { static { let a; let b; ({ a, b } = foo); } } - │ ^ + │ ^ ``` @@ -1326,15 +1326,15 @@ class C { static { let a; a = 0; console.log(a); } } ``` invalid.jsonc:1:20 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ class C { static { let a; a = 0; console.log(a); } } │ ^^^ - i 'a' is never re-assigned. + i 'a' is only assigned here. > 1 │ class C { static { let a; a = 0; console.log(a); } } - │ ^ + │ ^ ``` @@ -1348,22 +1348,22 @@ let { itemId, list } = {}, obj = []; console.log(itemId, list, obj); ``` invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares some variables which are never re-assigned. + ! This let declares some variables that are only assigned once. > 1 │ let { itemId, list } = {}, obj = []; console.log(itemId, list, obj); │ ^^^ - i 'itemId' is never re-assigned. + i 'itemId' is never reassigned. > 1 │ let { itemId, list } = {}, obj = []; console.log(itemId, list, obj); │ ^^^^^^ - i 'list' is never re-assigned. + i 'list' is never reassigned. > 1 │ let { itemId, list } = {}, obj = []; console.log(itemId, list, obj); │ ^^^^ - i 'obj' is never re-assigned. + i 'obj' is never reassigned. > 1 │ let { itemId, list } = {}, obj = []; console.log(itemId, list, obj); │ ^^^ @@ -1385,22 +1385,22 @@ let [ itemId, list ] = [], obj = []; console.log(itemId, list, obj); ``` invalid.jsonc:1:1 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares some variables which are never re-assigned. + ! This let declares some variables that are only assigned once. > 1 │ let [ itemId, list ] = [], obj = []; console.log(itemId, list, obj); │ ^^^ - i 'itemId' is never re-assigned. + i 'itemId' is never reassigned. > 1 │ let [ itemId, list ] = [], obj = []; console.log(itemId, list, obj); │ ^^^^^^ - i 'list' is never re-assigned. + i 'list' is never reassigned. > 1 │ let [ itemId, list ] = [], obj = []; console.log(itemId, list, obj); │ ^^^^ - i 'obj' is never re-assigned. + i 'obj' is never reassigned. > 1 │ let [ itemId, list ] = [], obj = []; console.log(itemId, list, obj); │ ^^^ @@ -1422,12 +1422,12 @@ class C { static { () => a; let a = 1; } }; ``` invalid.jsonc:1:29 lint/style/useConst FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ class C { static { () => a; let a = 1; } }; │ ^^^ - i 'a' is never re-assigned. + i 'a' is never reassigned. > 1 │ class C { static { () => a; let a = 1; } }; │ ^ @@ -1449,17 +1449,15 @@ let x; function foo() { bar(x); } x = 0; ``` invalid.jsonc:1:1 lint/style/useConst ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - ! This let declares a variable which is never re-assigned. + ! This let declares a variable that is only assigned once. > 1 │ let x; function foo() { bar(x); } x = 0; │ ^^^ - i 'x' is never re-assigned. + i 'x' is only assigned here. > 1 │ let x; function foo() { bar(x); } x = 0; - │ ^ + │ ^ ``` - - diff --git a/crates/biome_js_analyze/tests/specs/style/useConst/valid.jsonc b/crates/biome_js_analyze/tests/specs/style/useConst/valid.jsonc index e6e37abebc8a..d86eb696403e 100644 --- a/crates/biome_js_analyze/tests/specs/style/useConst/valid.jsonc +++ b/crates/biome_js_analyze/tests/specs/style/useConst/valid.jsonc @@ -98,5 +98,10 @@ // https://github.com/eslint/eslint/issues/16266 "let { itemId, list } = {}, obj = [], total = 0; total = 9; console.log(itemId, list, obj, total);", - "let [ itemId, list ] = [], total = 0; total = 9; console.log(itemId, list, total);" + "let [ itemId, list ] = [], total = 0; total = 9; console.log(itemId, list, total);", + + // Read before an assignement + "let x; x; x = 0;", + "let x; { x; }; x = 0;", + "let x; { { x; } }; x = 0;" ] diff --git a/crates/biome_js_analyze/tests/specs/style/useConst/valid.jsonc.snap b/crates/biome_js_analyze/tests/specs/style/useConst/valid.jsonc.snap index f5d93522a42f..03a57d0cf4d3 100644 --- a/crates/biome_js_analyze/tests/specs/style/useConst/valid.jsonc.snap +++ b/crates/biome_js_analyze/tests/specs/style/useConst/valid.jsonc.snap @@ -412,4 +412,17 @@ let { itemId, list } = {}, obj = [], total = 0; total = 9; console.log(itemId, l let [ itemId, list ] = [], total = 0; total = 9; console.log(itemId, list, total); ``` +# Input +```cjs +let x; x; x = 0; +``` + +# Input +```cjs +let x; { x; }; x = 0; +``` +# Input +```cjs +let x; { { x; } }; x = 0; +``` diff --git a/justfile b/justfile index dba5306ab5bc..3208d8498037 100644 --- a/justfile +++ b/justfile @@ -21,7 +21,7 @@ upgrade-tools: # Generate all files across crates and tools. You rarely want to use it locally. gen-all: cargo run -p xtask_codegen -- all - cargo run -p xtask_codegen -- configuration + cargo codegen-configuration cargo run -p xtask_codegen --features configuration -- migrate-eslint just gen-bindings just format diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index 6cd5884b252c..891e0728b650 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -1144,7 +1144,7 @@ export interface Style { */ useConsistentArrayType?: RuleConfiguration_for_ConsistentArrayTypeOptions; /** - * Require const declarations for variables that are never reassigned after declared. + * Require const declarations for variables that are only assigned once. */ useConst?: RuleConfiguration_for_Null; /** diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json index 9b603719da03..f6331662d009 100644 --- a/packages/@biomejs/biome/configuration_schema.json +++ b/packages/@biomejs/biome/configuration_schema.json @@ -2192,7 +2192,7 @@ ] }, "useConst": { - "description": "Require const declarations for variables that are never reassigned after declared.", + "description": "Require const declarations for variables that are only assigned once.", "anyOf": [ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" }