Skip to content

Commit eace435

Browse files
committed
feat(linter/eslint): Implement no-label-var
Rule Detail: [link](https://eslint.org/docs/latest/rules/no-label-var)
1 parent eb37918 commit eace435

File tree

3 files changed

+107
-0
lines changed

3 files changed

+107
-0
lines changed

crates/oxc_linter/src/rules.rs

+2
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ mod eslint {
7575
pub mod no_inner_declarations;
7676
pub mod no_irregular_whitespace;
7777
pub mod no_iterator;
78+
pub mod no_label_var;
7879
pub mod no_loss_of_precision;
7980
pub mod no_multi_str;
8081
pub mod no_new;
@@ -451,6 +452,7 @@ oxc_macros::declare_all_lint_rules! {
451452
eslint::no_case_declarations,
452453
eslint::no_class_assign,
453454
eslint::no_multi_str,
455+
eslint::no_label_var,
454456
eslint::require_await,
455457
eslint::no_compare_neg_zero,
456458
eslint::no_cond_assign,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
use oxc_ast::AstKind;
2+
use oxc_diagnostics::OxcDiagnostic;
3+
use oxc_macros::declare_oxc_lint;
4+
use oxc_span::Span;
5+
6+
use crate::{context::LintContext, rule::Rule, AstNode};
7+
8+
fn no_label_var_diagnostic(x0: &str, span0: Span, span1: Span) -> OxcDiagnostic {
9+
OxcDiagnostic::warn(format!(
10+
"eslint(no-label-var): Found identifier '{x0}' with the same name as a label."
11+
))
12+
.with_labels([
13+
span0.label(format!("Identifier '{x0}' found here.")),
14+
span1.label("Label with the same name."),
15+
])
16+
}
17+
18+
#[derive(Debug, Default, Clone)]
19+
pub struct NoLabelVar;
20+
21+
declare_oxc_lint!(
22+
/// ### What it does
23+
///
24+
/// Disallow labels that share a name with a variable.
25+
///
26+
/// ### Why is this bad?
27+
///
28+
/// This rule aims to create clearer code by disallowing the bad practice of creating a label
29+
/// that shares a name with a variable that is in scope.
30+
///
31+
/// ### Example
32+
/// ```javascript
33+
/// var x = foo;
34+
/// function bar() {
35+
/// x:
36+
/// for (;;) {
37+
/// break x;
38+
/// }
39+
/// }
40+
/// ```
41+
NoLabelVar,
42+
style,
43+
);
44+
45+
impl Rule for NoLabelVar {
46+
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
47+
let AstKind::LabeledStatement(labeled_stmt) = node.kind() else { return };
48+
49+
if let Some(symbol_id) =
50+
ctx.scopes().find_binding(node.scope_id(), &labeled_stmt.label.name)
51+
{
52+
let decl_span = ctx.symbols().get_span(symbol_id);
53+
let label_decl = labeled_stmt.span.start;
54+
ctx.diagnostic(no_label_var_diagnostic(
55+
&labeled_stmt.label.name,
56+
decl_span,
57+
Span::new(label_decl, label_decl + 1),
58+
));
59+
}
60+
}
61+
}
62+
63+
#[test]
64+
fn test() {
65+
use crate::tester::Tester;
66+
67+
let pass = vec![
68+
"function bar() { q: for(;;) { break q; } } function foo () { var q = t; }",
69+
"function bar() { var x = foo; q: for(;;) { break q; } }",
70+
];
71+
72+
let fail = vec![
73+
"var x = foo; function bar() { x: for(;;) { break x; } }",
74+
"function bar() { var x = foo; x: for(;;) { break x; } }",
75+
"function bar(x) { x: for(;;) { break x; } }",
76+
];
77+
78+
Tester::new(NoLabelVar::NAME, pass, fail).test_and_snapshot();
79+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
source: crates/oxc_linter/src/tester.rs
3+
---
4+
eslint(no-label-var): Found identifier 'x' with the same name as a label.
5+
╭─[no_label_var.tsx:1:5]
6+
1var x = foo; function bar() { x: for(;;) { break x; } }
7+
· ┬ ┬
8+
· │ ╰── Label with the same name.
9+
· ╰── Identifier 'x' found here.
10+
╰────
11+
12+
eslint(no-label-var): Found identifier 'x' with the same name as a label.
13+
╭─[no_label_var.tsx:1:22]
14+
1function bar() { var x = foo; x: for(;;) { break x; } }
15+
· ┬ ┬
16+
· │ ╰── Label with the same name.
17+
· ╰── Identifier 'x' found here.
18+
╰────
19+
20+
eslint(no-label-var): Found identifier 'x' with the same name as a label.
21+
╭─[no_label_var.tsx:1:14]
22+
1function bar(x) { x: for(;;) { break x; } }
23+
· ┬ ┬
24+
· │ ╰── Label with the same name.
25+
· ╰── Identifier 'x' found here.
26+
╰────

0 commit comments

Comments
 (0)