diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index d1f46910c..f7d2b63bd 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -92,6 +92,7 @@ mod eslint { pub mod no_setter_return; pub mod no_shadow_restricted_names; pub mod no_sparse_arrays; + pub mod no_ternary; pub mod no_this_before_super; pub mod no_undef; pub mod no_unsafe_finally; @@ -360,6 +361,7 @@ oxc_macros::declare_all_lint_rules! { eslint::for_direction, eslint::getter_return, eslint::max_lines, + eslint::no_ternary, eslint::no_this_before_super, eslint::no_array_constructor, eslint::no_async_promise_executor, diff --git a/crates/oxc_linter/src/rules/eslint/no_ternary.rs b/crates/oxc_linter/src/rules/eslint/no_ternary.rs new file mode 100644 index 000000000..af5c66ee8 --- /dev/null +++ b/crates/oxc_linter/src/rules/eslint/no_ternary.rs @@ -0,0 +1,62 @@ +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-ternary): Unexpected use of ternary expression")] +#[diagnostic(severity(warning), help("Do not use the ternary expression."))] +struct NoTernaryDiagnostic(#[label] pub Span); + +#[derive(Debug, Default, Clone)] +pub struct NoTernary; + +declare_oxc_lint!( + /// ### What it does + /// Disallow ternary operators + /// + /// ### Why is this bad? + /// The ternary operator is used to conditionally assign a value to a variable. Some believe that the use of ternary operators leads to unclear code. + /// + /// ### Example + /// ```javascript + /// var foo = isBar ? baz : qux; + // + // function quux() { + // return foo ? bar() : baz(); + // } + /// ``` + NoTernary, + style +); + +impl Rule for NoTernary { + fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + if let AstKind::ConditionalExpression(cond_expr) = node.kind() { + ctx.diagnostic(NoTernaryDiagnostic(Span::new( + cond_expr.span.start, + cond_expr.span.end, + ))); + } + } +} + +#[test] +fn test() { + use crate::tester::Tester; + + let pass = vec![r#""x ? y";"#, "if (true) { thing() } else { stuff() };"]; + + let fail = vec![ + "var foo = true ? thing : stuff;", + "true ? thing() : stuff();", + "function foo(bar) { return bar ? baz : qux; }", + ]; + + Tester::new(NoTernary::NAME, pass, fail).test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/no_ternary.snap b/crates/oxc_linter/src/snapshots/no_ternary.snap new file mode 100644 index 000000000..4354e0d9b --- /dev/null +++ b/crates/oxc_linter/src/snapshots/no_ternary.snap @@ -0,0 +1,24 @@ +--- +source: crates/oxc_linter/src/tester.rs +expression: no_ternary +--- + ⚠ eslint(no-ternary): Unexpected use of ternary expression + ╭─[no_ternary.tsx:1:11] + 1 │ var foo = true ? thing : stuff; + · ──────────────────── + ╰──── + help: Do not use the ternary expression. + + ⚠ eslint(no-ternary): Unexpected use of ternary expression + ╭─[no_ternary.tsx:1:1] + 1 │ true ? thing() : stuff(); + · ──────────────────────── + ╰──── + help: Do not use the ternary expression. + + ⚠ eslint(no-ternary): Unexpected use of ternary expression + ╭─[no_ternary.tsx:1:28] + 1 │ function foo(bar) { return bar ? baz : qux; } + · ─────────────── + ╰──── + help: Do not use the ternary expression.