diff --git a/crates/oxc_linter/src/rules/vitest/prefer_to_be_falsy.rs b/crates/oxc_linter/src/rules/vitest/prefer_to_be_falsy.rs index cabcf794a9533..75b6e80a893a0 100644 --- a/crates/oxc_linter/src/rules/vitest/prefer_to_be_falsy.rs +++ b/crates/oxc_linter/src/rules/vitest/prefer_to_be_falsy.rs @@ -1,10 +1,8 @@ use oxc_macros::declare_oxc_lint; -use crate::{ - context::LintContext, - rule::Rule, - utils::{collect_possible_jest_call_node, prefer_to_be_simply_bool}, -}; +use crate::{context::LintContext, rule::Rule, utils::collect_possible_jest_call_node}; + +use super::prefer_to_be_truthy::prefer_to_be_simply_bool; #[derive(Debug, Default, Clone)] pub struct PreferToBeFalsy; diff --git a/crates/oxc_linter/src/rules/vitest/prefer_to_be_truthy.rs b/crates/oxc_linter/src/rules/vitest/prefer_to_be_truthy.rs index 836f8160817e2..08e6d32c03706 100644 --- a/crates/oxc_linter/src/rules/vitest/prefer_to_be_truthy.rs +++ b/crates/oxc_linter/src/rules/vitest/prefer_to_be_truthy.rs @@ -1,11 +1,75 @@ +use oxc_ast::{ + ast::{Argument, Expression}, + AstKind, +}; use oxc_macros::declare_oxc_lint; use crate::{ context::LintContext, rule::Rule, - utils::{collect_possible_jest_call_node, prefer_to_be_simply_bool}, + utils::{ + collect_possible_jest_call_node, is_equality_matcher, + parse_expect_and_typeof_vitest_fn_call, PossibleJestNode, + }, }; +use oxc_diagnostics::OxcDiagnostic; +use oxc_span::Span; + +pub fn prefer_to_be_simply_bool<'a>( + possible_vitest_node: &PossibleJestNode<'a, '_>, + ctx: &LintContext<'a>, + value: bool, +) { + let node = possible_vitest_node.node; + let AstKind::CallExpression(call_expr) = node.kind() else { + return; + }; + let Some(vitest_expect_fn_call) = + parse_expect_and_typeof_vitest_fn_call(call_expr, possible_vitest_node, ctx) + else { + return; + }; + let Some(matcher) = vitest_expect_fn_call.matcher() else { + return; + }; + if !is_equality_matcher(matcher) || vitest_expect_fn_call.args.len() == 0 { + return; + } + let Some(arg_expr) = vitest_expect_fn_call.args.first().and_then(Argument::as_expression) + else { + return; + }; + + if let Expression::BooleanLiteral(arg) = arg_expr.get_inner_expression() { + if arg.value == value { + let span = Span::new(matcher.span.start, call_expr.span.end); + + let is_cmp_mem_expr = match matcher.parent { + Some(Expression::ComputedMemberExpression(_)) => true, + Some( + Expression::StaticMemberExpression(_) | Expression::PrivateFieldExpression(_), + ) => false, + _ => return, + }; + + let call_name = if value { "toBeTruthy" } else { "toBeFalsy" }; + + ctx.diagnostic_with_fix( + OxcDiagnostic::warn(format!("Use `{call_name}` instead.")).with_label(span), + |fixer| { + let new_matcher = if is_cmp_mem_expr { + format!("[\"{call_name}\"]()") + } else { + format!("{call_name}()") + }; + fixer.replace(span, new_matcher) + }, + ); + } + } +} + #[derive(Debug, Default, Clone)] pub struct PreferToBeTruthy; diff --git a/crates/oxc_linter/src/utils/vitest.rs b/crates/oxc_linter/src/utils/vitest.rs index 17ff25c533e40..4eb992ea59c91 100644 --- a/crates/oxc_linter/src/utils/vitest.rs +++ b/crates/oxc_linter/src/utils/vitest.rs @@ -1,14 +1,6 @@ -use oxc_ast::{ - ast::{Argument, CallExpression, Expression}, - AstKind, -}; -use oxc_diagnostics::OxcDiagnostic; -use oxc_span::Span; +use oxc_ast::ast::CallExpression; -use super::{ - is_equality_matcher, parse_jest_fn_call, ParsedExpectFnCall, ParsedJestFnCallNew, - PossibleJestNode, -}; +use super::{parse_jest_fn_call, ParsedExpectFnCall, ParsedJestFnCallNew, PossibleJestNode}; use crate::LintContext; mod valid_vitest_fn; @@ -27,57 +19,3 @@ pub fn parse_expect_and_typeof_vitest_fn_call<'a>( ParsedJestFnCallNew::GeneralJest(_) => None, } } - -pub fn prefer_to_be_simply_bool<'a>( - possible_vitest_node: &PossibleJestNode<'a, '_>, - ctx: &LintContext<'a>, - value: bool, -) { - let node = possible_vitest_node.node; - let AstKind::CallExpression(call_expr) = node.kind() else { - return; - }; - let Some(vitest_expect_fn_call) = - parse_expect_and_typeof_vitest_fn_call(call_expr, possible_vitest_node, ctx) - else { - return; - }; - let Some(matcher) = vitest_expect_fn_call.matcher() else { - return; - }; - if !is_equality_matcher(matcher) || vitest_expect_fn_call.args.len() == 0 { - return; - } - let Some(arg_expr) = vitest_expect_fn_call.args.first().and_then(Argument::as_expression) - else { - return; - }; - - if let Expression::BooleanLiteral(arg) = arg_expr.get_inner_expression() { - if arg.value == value { - let span = Span::new(matcher.span.start, call_expr.span.end); - - let is_cmp_mem_expr = match matcher.parent { - Some(Expression::ComputedMemberExpression(_)) => true, - Some( - Expression::StaticMemberExpression(_) | Expression::PrivateFieldExpression(_), - ) => false, - _ => return, - }; - - let call_name = if value { "toBeTruthy" } else { "toBeFalsy" }; - - ctx.diagnostic_with_fix( - OxcDiagnostic::warn(format!("Use `{call_name}` instead.")).with_label(span), - |fixer| { - let new_matcher = if is_cmp_mem_expr { - format!("[\"{call_name}\"]()") - } else { - format!("{call_name}()") - }; - fixer.replace(span, new_matcher) - }, - ); - } - } -}