You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor(eslint/block-scoped-var): clean up implementation and improve documentation (#13417)
## Refactor and Standardize: `eslint/block-scoped-var`
This PR refactors the implementation of the `block-scoped-var` rule to
make the codebase more **idiomatic Rust**, improving readability,
maintainability, and alignment with Rust best practices.
In addition, the rule documentation has been **standardized and
enhanced** following the documentation skeleton described in #13389.
### Changes included
* Refactored rule logic with clearer naming, early returns, and
idiomatic Rust patterns (`if let`, `Option`, `Iterator`, etc.).
* Improved structure for better readability and maintainability.
* Standardized rule documentation for consistency across the linter
rules.
> [!NOTE]
> This PR is focused solely on refactoring and documentation; no test
behavior is modified.
OxcDiagnostic::warn(format!("'{name}' is used outside of binding context."))
10
13
.with_help(format!("Variable '{name}' is used outside its declaration block. Declare it outside the block or use 'let'/'const'."))
11
14
.with_labels([
12
-
redecl_span.label("it is redeclared here"),
15
+
redeclare_span.label("it is redeclared here"),
13
16
decl_span.label(format!("'{name}' is first declared here")),
14
17
])
15
18
}
@@ -28,36 +31,96 @@ pub struct BlockScopedVar;
28
31
declare_oxc_lint!(
29
32
/// ### What it does
30
33
///
31
-
/// Generates warnings when variables are used outside of the block in which they were defined.
32
-
/// This emulates C-style block scope.
34
+
/// Enforces that variables are both **declared** and **used** within the same block scope.
35
+
/// This rule prevents accidental use of variables outside their intended block, mimicking C-style block scoping in JavaScript.
33
36
///
34
37
/// ### Why is this bad?
35
38
///
36
-
/// This rule aims to reduce the usage of variables outside of their binding context
37
-
/// and emulate traditional block scope from other languages.
38
-
/// This is to help newcomers to the language avoid difficult bugs with variable hoisting.
39
+
/// JavaScript’s `var` declarations are hoisted to the top of their enclosing function, which can cause variables declared in a block (e.g., inside an `if` or `for`) to be accessible outside of it.
40
+
/// This can lead to hard-to-find bugs.
41
+
/// By enforcing block scoping, this rule helps avoid hoisting issues and aligns more closely with how other languages treat block variables.
42
+
///
43
+
/// ### Options
44
+
///
45
+
/// No options available for this rule.
39
46
///
40
47
/// ### Examples
41
48
///
42
49
/// Examples of **incorrect** code for this rule:
43
50
/// ```js
51
+
/// /* block-scoped-var: "error" */
52
+
///
44
53
/// function doIf() {
45
54
/// if (true) {
46
55
/// var build = true;
47
56
/// }
48
57
/// console.log(build);
49
58
/// }
59
+
///
60
+
/// function doLoop() {
61
+
/// for (var i = 0; i < 10; i++) {
62
+
/// // do something
63
+
/// }
64
+
/// console.log(i); // i is accessible here
65
+
/// }
66
+
///
67
+
/// function doSomething() {
68
+
/// if (true) {
69
+
/// var foo = 1;
70
+
/// }
71
+
/// if (false) {
72
+
/// foo = 2;
73
+
/// }
74
+
/// }
75
+
///
76
+
/// function doTry() {
77
+
/// try {
78
+
/// var foo = 1;
79
+
/// } catch (e) {
80
+
/// console.log(foo);
81
+
/// }
82
+
/// }
83
+
///
50
84
/// ```
51
85
///
52
86
/// Examples of **correct** code for this rule:
53
87
/// ```js
88
+
/// /* block-scoped-var: "error" */
89
+
///
54
90
/// function doIf() {
55
91
/// var build;
56
92
/// if (true) {
57
93
/// build = true;
58
-
/// }
94
+
/// }
59
95
/// console.log(build);
60
96
/// }
97
+
///
98
+
/// function doLoop() {
99
+
/// var i;
100
+
/// for (i = 0; i < 10; i++) {
101
+
/// // do something
102
+
/// }
103
+
/// console.log(i);
104
+
/// }
105
+
///
106
+
/// function doSomething() {
107
+
/// var foo;
108
+
/// if (true) {
109
+
/// foo = 1;
110
+
/// }
111
+
/// if (false) {
112
+
/// foo = 2;
113
+
/// }
114
+
/// }
115
+
///
116
+
/// function doTry() {
117
+
/// var foo;
118
+
/// try {
119
+
/// foo = 1;
120
+
/// } catch (e) {
121
+
/// console.log(foo);
122
+
/// }
123
+
/// }
61
124
/// ```
62
125
BlockScopedVar,
63
126
eslint,
@@ -72,54 +135,86 @@ impl Rule for BlockScopedVar {
72
135
if decl.kind != VariableDeclarationKind::Var{
73
136
return;
74
137
}
75
-
letcur_node_scope_id = node.scope_id();
76
-
if !ctx.scoping().scope_flags(cur_node_scope_id).is_strict_mode(){
138
+
letscope_id = node.scope_id();
139
+
if !ctx.scoping().scope_flags(scope_id).is_strict_mode(){
77
140
return;
78
141
}
79
-
// `scope_arr` contains all the scopes that are children of the current scope
142
+
// `scope_ids` contains all the scopes that are children of the current scope
0 commit comments