diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 440312168..98e87b049 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -103,6 +103,7 @@ mod eslint { pub mod no_useless_rename; pub mod no_var; pub mod no_void; + pub mod no_with; pub mod require_yield; pub mod use_isnan; pub mod valid_typeof; @@ -417,6 +418,7 @@ oxc_macros::declare_all_lint_rules! { eslint::no_useless_rename, eslint::no_var, eslint::no_void, + eslint::no_with, eslint::require_yield, eslint::use_isnan, eslint::valid_typeof, diff --git a/crates/oxc_linter/src/rules/eslint/no_with.rs b/crates/oxc_linter/src/rules/eslint/no_with.rs new file mode 100644 index 000000000..32161ca50 --- /dev/null +++ b/crates/oxc_linter/src/rules/eslint/no_with.rs @@ -0,0 +1,56 @@ +use oxc_ast::AstKind; +use oxc_diagnostics::{ + miette::{self, Diagnostic}, + thiserror::Error, +}; +use oxc_macros::declare_oxc_lint; +use oxc_span::Span; + +use crate::{context::LintContext, rule::Rule, AstNode}; + +#[derive(Debug, Error, Diagnostic)] +#[error("eslint(no-with): Unexpected use of `with` statement.")] +#[diagnostic(severity(warning), help("Do not use the `with` statement."))] +struct NoWithDiagnostic(#[label] pub Span); + +#[derive(Debug, Default, Clone)] +pub struct NoWith; + +declare_oxc_lint!( + /// ### What it does + /// Disallow `with` statements + /// + /// ### Why is this bad? + /// The with statement is potentially problematic because it adds members of an object to the current scope, making it impossible to tell what a variable inside the block actually refers to. + /// + /// ### Example + /// ```javascript + /// with (point) { + /// r = Math.sqrt(x * x + y * y); // is r a member of point? + /// } + /// ``` + NoWith, + correctness +); + +impl Rule for NoWith { + fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + if let AstKind::WithStatement(with_statement) = node.kind() { + ctx.diagnostic(NoWithDiagnostic(Span::new( + with_statement.span.start, + with_statement.span.start + 4, + ))); + } + } +} + +#[test] +fn test() { + use crate::tester::Tester; + + let pass = vec!["foo.bar()"]; + + let fail = vec!["with(foo) { bar() }"]; + + Tester::new(NoWith::NAME, pass, fail).test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/no_with.snap b/crates/oxc_linter/src/snapshots/no_with.snap new file mode 100644 index 000000000..33e12191f --- /dev/null +++ b/crates/oxc_linter/src/snapshots/no_with.snap @@ -0,0 +1,10 @@ +--- +source: crates/oxc_linter/src/tester.rs +expression: no_with +--- + ⚠ eslint(no-with): Unexpected use of `with` statement. + ╭─[no_with.tsx:1:1] + 1 │ with(foo) { bar() } + · ──── + ╰──── + help: Do not use the `with` statement.