From 91e8a712148d9c157f47d3fc47f7d96d26b98179 Mon Sep 17 00:00:00 2001 From: Andi Pabst Date: Sun, 17 Mar 2024 12:53:55 +0100 Subject: [PATCH] feat(linter): eslint/no-with (#2741) Relates to #479 Rule detail: https://eslint.org/docs/latest/rules/no-with --- crates/oxc_linter/src/rules.rs | 2 + crates/oxc_linter/src/rules/eslint/no_with.rs | 56 +++++++++++++++++++ crates/oxc_linter/src/snapshots/no_with.snap | 10 ++++ 3 files changed, 68 insertions(+) create mode 100644 crates/oxc_linter/src/rules/eslint/no_with.rs create mode 100644 crates/oxc_linter/src/snapshots/no_with.snap diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 4403121687c13..98e87b0492719 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 0000000000000..32161ca5072e0 --- /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 0000000000000..33e12191fb10a --- /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.