diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 273a05f34..0d8af66c0 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -84,7 +84,6 @@ mod eslint { pub mod no_irregular_whitespace; pub mod no_iterator; pub mod no_loss_of_precision; - pub mod no_mixed_operators; pub mod no_new_native_nonconstructor; pub mod no_new_wrappers; pub mod no_nonoctal_decimal_escape; @@ -93,7 +92,6 @@ mod eslint { pub mod no_prototype_builtins; pub mod no_redeclare; pub mod no_regex_spaces; - pub mod no_return_await; pub mod no_script_url; pub mod no_self_assign; pub mod no_self_compare; @@ -443,7 +441,6 @@ oxc_macros::declare_all_lint_rules! { eslint::no_irregular_whitespace, eslint::no_iterator, eslint::no_loss_of_precision, - eslint::no_mixed_operators, eslint::no_new_wrappers, eslint::no_nonoctal_decimal_escape, eslint::no_obj_calls, @@ -451,7 +448,6 @@ oxc_macros::declare_all_lint_rules! { eslint::no_prototype_builtins, eslint::no_redeclare, eslint::no_regex_spaces, - eslint::no_return_await, eslint::no_script_url, eslint::no_self_assign, eslint::no_self_compare, diff --git a/crates/oxc_linter/src/rules/eslint/no_mixed_operators.rs b/crates/oxc_linter/src/rules/eslint/no_mixed_operators.rs deleted file mode 100644 index cc0fc9c66..000000000 --- a/crates/oxc_linter/src/rules/eslint/no_mixed_operators.rs +++ /dev/null @@ -1,376 +0,0 @@ -use oxc_ast::AstKind; -use oxc_diagnostics::{ - miette::{self, Diagnostic}, - thiserror::{self, Error}, -}; -use oxc_macros::declare_oxc_lint; -use oxc_semantic::AstNode; -use oxc_span::{GetSpan, Span}; - -use crate::{context::LintContext, rule::Rule}; - -#[derive(Debug, Error, Diagnostic)] -#[error("eslint(no-mixed-operators): Unexpected mix of {0} with {1}")] -#[diagnostic( - severity(warning), - help("Use parentheses to clarify the intended order of operations.") -)] -struct NoMixedOperatorsDiagnostic( - &'static str, /*Node Operator */ - &'static str, /*Parent Operator */ - #[label] pub Span, /*Span of the node operator */ - #[label] pub Span, /*Span of the parent operator */ -); - -#[derive(Debug, Default, Clone, Eq, PartialEq)] -pub struct NoMixedOperators(Box); - -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct NoMixedOperatorsConfig { - /// Disallow Mixed operators within one group. - groups: Vec>, - /// Allow operators of the same precedence to be mixed. - allow_same_precedence: bool, -} - -impl std::ops::Deref for NoMixedOperators { - type Target = NoMixedOperatorsConfig; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl Default for NoMixedOperatorsConfig { - fn default() -> Self { - Self { groups: default_groups(), allow_same_precedence: true } - } -} - -declare_oxc_lint! { - /// ### What it does - /// Disallow mixed binary operators. - /// - /// ### Why is this bad? - /// Enclosing complex expressions by parentheses clarifies the developer’s intention, - /// which makes the code more readable. This rule warns when different operators - /// are used consecutively without parentheses in an expression. - /// - /// ### Examples - /// ```javascript - /// var foo = a && b || c || d; /*BAD: Unexpected mix of '&&' and '||'.*/ - /// var foo = (a && b) || c || d; /*GOOD*/ - /// var foo = a && (b || c || d); /*GOOD*/ - /// ``` - NoMixedOperators, - pedantic, -} - -impl Rule for NoMixedOperators { - fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { - let node_kind = node.kind(); - if !matches!(node_kind, AstKind::BinaryExpression(_) | AstKind::LogicalExpression(_)) { - return; - } - - let Some(parent_kind) = ctx.nodes().parent_kind(node.id()) else { return }; - - if !matches!( - parent_kind, - AstKind::BinaryExpression(_) - | AstKind::LogicalExpression(_) - | AstKind::ConditionalExpression(_) - ) { - return; - } - - // Now we know that node is a BinaryExpression or LogicalExpression, and parent - // is a BinaryExpression or LogicalExpression or ConditionalExpression. - if Self::is_mixed_with_parent(node_kind, parent_kind) { - self.report(node_kind, parent_kind, ctx); - } - } - - fn from_configuration(value: serde_json::Value) -> Self { - Self::try_from_configuration(&value).unwrap_or_default() - } -} - -impl NoMixedOperators { - pub fn try_from_configuration(value: &serde_json::Value) -> Option { - let config = value.get(0)?; - - let mut groups = vec![]; - if let Some(groups_config) = config.get("groups") { - if let Some(groups_config) = groups_config.as_array() { - 'outer: for group_config in groups_config { - // Parse current group configuration. On failure fall through to next group. - if let Some(group_config) = group_config.as_array() { - let mut group = vec![]; - for val in group_config { - let Some(val) = val.as_str() else { continue 'outer }; - let Some((operator, _)) = operator_and_precedence(val) else { - continue 'outer; - }; - group.push(operator); - } - groups.push(group); - } - } - } - } - - if groups.is_empty() { - groups = default_groups(); - } - - let allow_same_precedence = - config.get("allowSamePrecedence").map_or(true, |val| val.as_bool().unwrap_or_default()); - - Some(Self(Box::new(NoMixedOperatorsConfig { groups, allow_same_precedence }))) - } - - fn is_mixed_with_parent(node: AstKind, parent: AstKind) -> bool { - match (node, parent) { - (AstKind::BinaryExpression(node), AstKind::BinaryExpression(parent)) => { - node.operator != parent.operator - } - (AstKind::LogicalExpression(node), AstKind::LogicalExpression(parent)) => { - node.operator != parent.operator - } - _ => true, - } - // Note that there is not need to check for parenthesis explicitly because if an - // expression is parenthesized, its parent node is a ParenthesizedExpression and will - // never enter the code path. - } - - /// Report mixed operator pare between node and parent corresponding to configuration. - fn report(&self, node: AstKind, parent: AstKind, ctx: &LintContext<'_>) { - let (node_operator, node_left_span, node_right_span) = match node { - AstKind::BinaryExpression(expr) => { - (expr.operator.as_str(), expr.left.span(), expr.right.span()) - } - AstKind::LogicalExpression(expr) => { - (expr.operator.as_str(), expr.left.span(), expr.right.span()) - } - _ => unreachable!(), - }; - // Since we don't store the exact span of the operators, approximate that span to be between the lhs - // and rhs of the expression. - let node_operator_span = get_op_span(node_left_span, node_right_span, node_operator, ctx); - - let (parent_operator, parent_left_span, parent_right_span) = match parent { - AstKind::BinaryExpression(expr) => { - (expr.operator.as_str(), expr.left.span(), expr.right.span()) - } - AstKind::LogicalExpression(expr) => { - (expr.operator.as_str(), expr.left.span(), expr.right.span()) - } - AstKind::ConditionalExpression(expr) => { - // For conditional operators, the span covers both ? and : - ("?:", expr.test.span(), expr.alternate.span()) - } - _ => unreachable!(), - }; - let parent_operator_span = - get_op_span(parent_left_span, parent_right_span, parent_operator, ctx); - - let (node_operator, node_precedence) = operator_and_precedence(node_operator).unwrap(); - let (parent_operator, parent_precedence) = - operator_and_precedence(parent_operator).unwrap(); - if !(self.allow_same_precedence && node_precedence == parent_precedence) - && self.in_the_same_group(node_operator, parent_operator) - { - // Report error at both operators - ctx.diagnostic(NoMixedOperatorsDiagnostic( - node_operator, - parent_operator, - node_operator_span, - parent_operator_span, - )); - } - } - - fn in_the_same_group(&self, op1: &str, op2: &str) -> bool { - self.groups.iter().any(|group| { - let mut contains_op1 = false; - let mut contains_op2 = false; - for &op in group { - if op == op1 { - contains_op1 = true; - } - if op == op2 { - contains_op2 = true; - } - } - contains_op1 && contains_op2 - }) - } -} - -#[rustfmt::skip] -static OPERATORS: [&str; 27] = [ - "+", "-", "*", "/", "%", "**", /* Arithmetic operator: 6 */ - "&", "|", "^", "~", "<<", ">>", ">>>", /*Bitwise operator: 13 */ - "==", "!=", "===", "!==", ">", ">=", "<", "<=", /*Compare operator: 21 */ - "&&", "||", /*Logical operator: 23 */ - "in", "instanceof", /*Relational operator: 25 */ - "?:", /*Conditional operator */ - "??", /*Coalesce operator */ -]; - -/// `https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#table` -#[rustfmt::skip] -const PRECEDENCES: [u8; 27] = [ - 11, 11, 12, 12, 12, 13, - 7, 5, 6, 14, 10, 10, 10, - 8, 8, 8, 8, 9, 9, 9, 9, - 4, 3, - 9, 9, - 2, - 3 -]; - -#[inline] -fn default_groups() -> Vec> { - let arithmetic: &[&str] = &OPERATORS[..6]; - let bitwise: &[&str] = &OPERATORS[6..13]; - let compare: &[&str] = &OPERATORS[13..21]; - let logical: &[&str] = &OPERATORS[21..23]; - let relational: &[&str] = &OPERATORS[23..25]; - let default_operators: [&[&str]; 5] = [arithmetic, bitwise, compare, logical, relational]; - default_operators.iter().map(|operators| operators.to_vec()).collect() -} - -#[inline] -fn operator_and_precedence(operator: &str) -> Option<(&'static str, u8)> { - OPERATORS.iter().position(|op| *op == operator).map(|idx| (OPERATORS[idx], PRECEDENCES[idx])) -} - -#[allow(clippy::cast_possible_truncation)] -fn get_op_span( - node_left_span: Span, - node_right_span: Span, - node_operator: &str, - ctx: &LintContext<'_>, -) -> Span { - Span::new(node_left_span.end, node_right_span.start) - .source_text(ctx.source_text()) - .find(node_operator) - .map_or_else( - || Span::new(node_left_span.end, node_right_span.start), - |v| { - let length = node_operator.len() as u32; - let length = if length == 1 { 0 } else { length }; - Span::new(node_left_span.end + v as u32, node_left_span.end + v as u32 + length) - }, - ) -} - -#[test] -fn test() { - use serde_json::json; - - use crate::tester::Tester; - - let pass = vec![ - ("a && b && c && d", None), - ("a || b || c || d", None), - ("(a || b) && c && d", None), - ("a || (b && c && d)", None), - ("(a || b || c) && d", None), - ("a || b || (c && d)", None), - ("a + b + c + d", None), - ("a * b * c * d", None), - ("a == 0 && b == 1", None), - ("a == 0 || b == 1", None), - ("(a == 0) && (b == 1)", Some(json!([{"groups": [["&&", "=="]]}]))), - ("a + b - c * d / e", Some(json!([{ "groups": [["&&", "||"]] }]))), - ("a + b - c", None), - ("a * b / c", None), - ("a + b - c", Some(json!([{ "allowSamePrecedence": true }]))), - ("a * b / c", Some(json!([{ "allowSamePrecedence": true }]))), - ("(a || b) ? c : d", Some(json!([{ "groups": [["&&", "||", "?:"]] }]))), - ("a ? (b || c) : d", Some(json!([{ "groups": [["&&", "||", "?:"]] }]))), - ("a ? b : (c || d)", Some(json!([{ "groups": [["&&", "||", "?:"]] }]))), - ("a || (b ? c : d)", Some(json!([{ "groups": [["&&", "||", "?:"]] }]))), - ("(a ? b : c) || d", Some(json!([{ "groups": [["&&", "||", "?:"]] }]))), - ("a || (b ? c : d)", None), - ("(a || b) ? c : d", None), - ("a || b ? c : d", None), - ("a ? (b || c) : d", None), - ("a ? b || c : d", None), - ("a ? b : (c || d)", None), - ("a ? b : c || d", None), - ]; - - let fail = vec![ - ("a && b || c", None), - ("a && b > 0 || c", Some(json!([{ "groups": [["&&", "||", ">"]] }]))), - ("a && b > 0 || c", Some(json!([{ "groups": [["&&", "||"]] }]))), - ( - "a && b + c - d / e || f", - Some(json!([{ "groups": [["&&", "||"], ["+", "-", "*", "/"]] }])), - ), - ( - "a && b + c - d / e || f", - Some( - json!([{ "groups": [["&&", "||"], ["+", "-", "*", "/"]], "allowSamePrecedence": true }]), - ), - ), - ("a + b - c", Some(json!([{ "allowSamePrecedence": false }]))), - ("a * b / c", Some(json!([{ "allowSamePrecedence": false }]))), - ("a || b ? c : d", Some(json!([{ "groups": [["&&", "||", "?:"]] }]))), - ("a && b ? 1 : 2", Some(json!([{ "groups": [["&&", "||", "?:"]] }]))), - ("x ? a && b : 0", Some(json!([{ "groups": [["&&", "||", "?:"]] }]))), - ("x ? 0 : a && b", Some(json!([{ "groups": [["&&", "||", "?:"]] }]))), - ("a + b ?? c", Some(json!([{ "groups": [["+", "??"]] }]))), - ("a in b ?? c", Some(json!([{ "groups": [["in", "??"]] }]))), - ("var y = 1.0 - 1/65536.0;", None), - ("var y = 1.0 - 1 /65536.0;", None), - ("var y = 1.0 - 1/ 65536.0;", None), - ("var y = 1.0- 1 / 65536.0;", None), - ("var y = 1.0 -1 / 65536.0;", None), - ("var y = 1.0-1 / 65536.0;", None), - ]; - - Tester::new(NoMixedOperators::NAME, pass, fail).test_and_snapshot(); -} - -#[cfg(test)] -mod internal_tests { - use serde_json::json; - - use super::*; - - #[test] - fn test_from_configuration() { - let config = json!([{ - "groups": [ - ["+", "-", "*", "/", "%", "**"], - ["&", "|", "^", "~", "<<", ">>", ">>>"], - ["==", "!=", "===", "!==", ">", ">=", "<", "<="], - ["&&", "||"], - ["in", "instanceof"] - ], - "allowSamePrecedence": true - }]); - let rule = NoMixedOperators::try_from_configuration(&config); - assert_eq!(Some(NoMixedOperators::default()), rule); - } - - #[test] - fn test_nornmalize_configuration() { - let config = json!([ - { "allowSamePrecedence": false } - ]); - let rule = NoMixedOperators::try_from_configuration(&config); - // missing groups should fall back to default - let expected = NoMixedOperators(Box::new(NoMixedOperatorsConfig { - groups: default_groups(), - allow_same_precedence: false, - })); - assert_eq!(Some(expected), rule); - } -} diff --git a/crates/oxc_linter/src/rules/eslint/no_return_await.rs b/crates/oxc_linter/src/rules/eslint/no_return_await.rs deleted file mode 100644 index 8856560cf..000000000 --- a/crates/oxc_linter/src/rules/eslint/no_return_await.rs +++ /dev/null @@ -1,262 +0,0 @@ -use oxc_ast::AstKind; -use oxc_diagnostics::{ - miette::{self, Diagnostic}, - thiserror::Error, -}; -use oxc_macros::declare_oxc_lint; -use oxc_span::{GetSpan, Span}; - -use crate::{context::LintContext, fixer::Fix, rule::Rule, AstNode}; - -#[derive(Debug, Error, Diagnostic)] -#[error("eslint(no-return-await): Redundant use of `await` on a return value.")] -#[diagnostic(severity(warning), help("Remove redundant `await`."))] -struct NoReturnAwaitDiagnostic(#[label] pub Span); - -#[derive(Debug, Default, Clone)] -pub struct NoReturnAwait; - -declare_oxc_lint!( - /// ### What it does - /// Disallow unnecessary return await - /// - /// ### Why is this bad? - /// This rule aims to prevent a likely common performance hazard due to a lack of understanding of the semantics of async function. - /// https://eslint.org/docs/latest/rules/no-return-await - /// - /// ### Example - /// ```javascript - /// async function foo() { - /// return await bar(); - /// } - /// ``` - NoReturnAwait, - pedantic -); - -impl Rule for NoReturnAwait { - fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { - if let AstKind::AwaitExpression(await_expr) = node.kind() { - if is_in_tail_call_position(node, ctx) && !has_error_handler(node, ctx) { - let start = await_expr.span.start; - let end = start + 5; - let await_keyword_span = Span::new(start, end); - ctx.diagnostic_with_fix(NoReturnAwaitDiagnostic(await_keyword_span), || { - Fix::new("", await_keyword_span) - }); - } - } - } -} - -fn is_in_tail_call_position<'a>(node: &AstNode<'a>, ctx: &LintContext<'a>) -> bool { - if let Some(parent) = ctx.nodes().parent_node(node.id()) { - let parent_kind = parent.kind(); - match parent_kind { - AstKind::ArrowFunctionExpression(arrow_expr) => { - // async () => { await b(); }) - // `epxression` property is false - return arrow_expr.expression; - } - AstKind::ReturnStatement(_) => { - return !has_error_handler(node, ctx); - } - AstKind::ConditionalExpression(cond_expr) => { - if (cond_expr.consequent.span() == node.kind().span()) - || (cond_expr.alternate.span() == node.kind().span()) - { - return is_in_tail_call_position(parent, ctx); - } - } - AstKind::LogicalExpression(logic_expr) => { - if logic_expr.right.span() == node.kind().span() { - return is_in_tail_call_position(parent, ctx); - } - } - AstKind::SequenceExpression(seq_expr) => { - if let Some(seq_expr_last) = seq_expr.expressions.last() { - if seq_expr_last.span() == node.kind().span() { - return is_in_tail_call_position(parent, ctx); - } - } - } - // `return (await b())` - AstKind::ParenthesizedExpression(paren_expr) => { - if paren_expr.expression.span() == node.kind().span() { - return is_in_tail_call_position(parent, ctx); - } - } - // async () => await bar() - AstKind::ExpressionStatement(expr_stat) => { - // expression state in the last line of a `function_body` - if expr_stat.expression.span() == node.kind().span() { - return is_in_tail_call_position(parent, ctx); - } - } - // last statement in `func_body` - AstKind::FunctionBody(func_body) => { - if let Some(func_body_stat_last) = func_body.statements.last() { - if func_body_stat_last.span() == node.kind().span() { - return is_in_tail_call_position(parent, ctx); - } - } - } - _ => { - return false; - } - } - } - false -} - -fn has_error_handler<'a>(node: &AstNode<'a>, ctx: &LintContext<'a>) -> bool { - let mut current_node = node; - loop { - if let Some(parent_node) = ctx.nodes().parent_node(current_node.id()) { - let parent_node_kind = parent_node.kind(); - if matches!(parent_node_kind, AstKind::Program(_)) { - break; - } - - if parent_node_kind.is_function_like() { - break; - } - - if let AstKind::TryStatement(try_stat) = parent_node_kind { - let current_node_span = current_node.kind().span(); - // try statement must have a `catch` or `finally` - if try_stat.block.span == current_node_span { - return true; - } - - // return await in `catch clause` with `finally` would be passed - if let Some(catch_clause) = &try_stat.handler { - if catch_clause.span == current_node_span && try_stat.finalizer.is_some() { - return true; - } - } - } - - current_node = parent_node; - } - } - false -} - -#[test] -fn test() { - use crate::tester::Tester; - - let pass = vec![ - ("\nasync () => { await b(); }", None), - ("\nasync function foo() {\n\tawait bar(); return;\n}\n", None), - ("\nasync function foo() {\n\tconst x = await bar(); return x;\n}\n", None), - ("\nasync () => { return bar(); }\n", None), - ("\nasync () => bar()\n", None), - ( - "\nasync function foo() {\nif (a) {\n\t\tif (b) {\n\t\t\treturn bar();\n\t\t}\n\t}\n}\n", - None, - ), - ("\nasync () => {\nif (a) {\n\t\tif (b) {\n\t\t\treturn bar();\n\t\t}\n\t}\n}\n", None), - ("\nasync function foo() {\n\treturn (await bar() && a);\n}\n", None), - ("\nasync function foo() {\n\treturn (await bar() || a);\n}\n", None), - ("\nasync function foo() {\n\treturn (a && await baz() && b);\n}\n", None), - ("\nasync function foo() {\n\treturn (await bar(), a);\n}\n", None), - ("\nasync function foo() {\n\treturn (await baz(), await bar(), a);\n}\n", None), - ("\nasync function foo() {\n\treturn (a, b, (await bar(), c));\n}\n", None), - ("\nasync function foo() {\n\treturn (await bar() ? a : b);\n}\n", None), - ("\nasync function foo() {\n\treturn ((a && await bar()) ? b : c);\n}\n", None), - ("\nasync function foo() {\n\treturn (baz() ? (await bar(), a) : b);\n}\n", None), - ("\nasync function foo() {\n\treturn (baz() ? (await bar() && a) : b);\n}\n", None), - ("\nasync function foo() {\n\treturn (baz() ? a : (await bar(), b));\n}\n", None), - ("\nasync function foo() {\n\treturn (baz() ? a : (await bar() && b));\n}\n", None), - ("\nasync () => (await bar(), a)\n", None), - ("\nasync () => (await bar() && a)\n", None), - ("\nasync () => (await bar() || a)\n", None), - ("\nasync () => (a && await bar() && b)\n", None), - ("\nasync () => (await baz(), await bar(), a)\n", None), - ("\nasync () => (a, b, (await bar(), c))\n", None), - ("\nasync () => (await bar() ? a : b)\n", None), - ("\nasync () => ((a && await bar()) ? b : c)\n", None), - ("\nasync () => (baz() ? (await bar(), a) : b)\n", None), - ("\nasync () => (baz() ? (await bar() && a) : b)\n", None), - ("\nasync () => (baz() ? a : (await bar(), b))\n", None), - ("\nasync () => (baz() ? a : (await bar() && b))\n", None), - ( - "\n async function foo() {\n try {\n return await bar();\n } catch (e) {\n baz();\n }\n }\n ", - None, - ), - ( - "\n async function foo() {\n try {\n return await bar();\n } finally {\n baz();\n }\n }\n ", - None, - ), - ( - "\n async function foo() {\n try {}\n catch (e) {\n return await bar();\n } finally {\n baz();\n }\n }\n ", - None, - ), - ( - "\n async function foo() {\n try {\n try {}\n finally {\n return await bar();\n }\n } finally {\n baz();\n }\n }\n ", - None, - ), - ( - "\n async function foo() {\n try {\n try {}\n catch (e) {\n return await bar();\n }\n } finally {\n baz();\n }\n }\n ", - None, - ), - ( - "\n async function foo() {\n try {\n return (a, await bar());\n } catch (e) {\n baz();\n }\n }\n ", - None, - ), - ( - "\n async function foo() {\n try {\n return (qux() ? await bar() : b);\n } catch (e) {\n baz();\n }\n }\n ", - None, - ), - ( - "\n async function foo() {\n try {\n return (a && await bar());\n } catch (e) {\n baz();\n }\n }\n ", - None, - ), - ]; - - let fail = vec![ - ("\nasync function foo() {\n\treturn await bar();\n}\n", None), - ("\nasync function foo() {\n\treturn await(bar());\n}\n", None), - ("\nasync function foo() {\n\treturn (a, await bar());\n}\n", None), - ("\nasync function foo() {\n\treturn (a, b, await bar());\n}\n", None), - ("\nasync function foo() {\n\treturn (a && await bar());\n}\n", None), - ("\nasync function foo() {\n\treturn (a && b && await bar());\n}\n", None), - ("\nasync function foo() {\n\treturn (a || await bar());\n}\n", None), - ("\nasync function foo() {\n\treturn (a, b, (c, d, await bar()));\n}\n", None), - ("\nasync function foo() {\n\treturn (a, b, (c && await bar()));\n}\n", None), - ("\nasync function foo() {\n\treturn (await baz(), b, await bar());\n}\n", None), - ("\nasync function foo() {\n\treturn (baz() ? await bar() : b);\n}\n", None), - ("\nasync function foo() {\n\treturn (baz() ? a : await bar());\n}\n", None), - ("\nasync function foo() {\n\treturn (baz() ? (a, await bar()) : b);\n}\n", None), - ("\nasync function foo() {\n\treturn (baz() ? a : (b, await bar()));\n}\n", None), - ("\nasync function foo() {\n\treturn (baz() ? (a && await bar()) : b);\n}\n", None), - ("\nasync function foo() {\n\treturn (baz() ? a : (b && await bar()));\n}\n", None), - ("\nasync () => { return await bar(); }\n", None), - ("\nasync () => await bar()\n", None), - ("\nasync () => (a, b, await bar())\n", None), - ("\nasync () => (a && await bar())\n", None), - ("\nasync () => (baz() ? await bar() : b)\n", None), - ("\nasync () => (baz() ? a : (b, await bar()))\n", None), - ("\nasync () => (baz() ? a : (b && await bar()))\n", None), - ("\nasync function foo() {\nif (a) {\n\t\tif (b) {\n\t\t\treturn await bar();\n\t\t}\n\t}\n}\n", None), - ("\nasync () => {\nif (a) {\n\t\tif (b) {\n\t\t\treturn await bar();\n\t\t}\n\t}\n}\n", None), - ("\nasync function foo() { try {}\nfinally {\nreturn await bar();\n}\n}\n", None), - ("\nasync function foo() {\ntry {}\ncatch (e) {\nreturn await bar();\n}\n}\n", None), - ("\ntry {\nasync function foo() {\nreturn await bar();\n}\n} catch (e) {}\n", None), - ("\ntry {\nasync () => await bar();\n} catch (e) {}\n", None), - ( - "\nasync function foo() {\ntry {}\ncatch (e) {\ntry {}\ncatch (e) {\n return await bar();\n}\n}\n}\n", - None, - ), - ( - "\nasync function foo() {\nreturn await new Promise(resolve => {\nresolve(5);\n});\n}\n", - None, - ), - ("\nasync () => {\nreturn await (\nfoo()\n)\n};\n", None), - ("\nasync function foo() {\nreturn await // Test\n5;\n}\n", None), - ]; - - Tester::new(NoReturnAwait::NAME, pass, fail).test_and_snapshot(); -} diff --git a/crates/oxc_linter/src/snapshots/no_mixed_operators.snap b/crates/oxc_linter/src/snapshots/no_mixed_operators.snap deleted file mode 100644 index b91b70d1b..000000000 --- a/crates/oxc_linter/src/snapshots/no_mixed_operators.snap +++ /dev/null @@ -1,157 +0,0 @@ ---- -source: crates/oxc_linter/src/tester.rs -expression: no_mixed_operators ---- - ⚠ eslint(no-mixed-operators): Unexpected mix of && with || - ╭─[no_mixed_operators.tsx:1:3] - 1 │ a && b || c - · ── ── - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of && with || - ╭─[no_mixed_operators.tsx:1:3] - 1 │ a && b > 0 || c - · ── ── - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of > with && - ╭─[no_mixed_operators.tsx:1:3] - 1 │ a && b > 0 || c - · ── ▲ - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of && with || - ╭─[no_mixed_operators.tsx:1:3] - 1 │ a && b > 0 || c - · ── ── - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of && with || - ╭─[no_mixed_operators.tsx:1:3] - 1 │ a && b + c - d / e || f - · ── ── - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of / with - - ╭─[no_mixed_operators.tsx:1:12] - 1 │ a && b + c - d / e || f - · ▲ ▲ - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of && with || - ╭─[no_mixed_operators.tsx:1:3] - 1 │ a && b + c - d / e || f - · ── ── - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of / with - - ╭─[no_mixed_operators.tsx:1:12] - 1 │ a && b + c - d / e || f - · ▲ ▲ - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of + with - - ╭─[no_mixed_operators.tsx:1:3] - 1 │ a + b - c - · ▲ ▲ - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of * with / - ╭─[no_mixed_operators.tsx:1:3] - 1 │ a * b / c - · ▲ ▲ - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of || with ?: - ╭─[no_mixed_operators.tsx:1:3] - 1 │ a || b ? c : d - · ── ─────── - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of && with ?: - ╭─[no_mixed_operators.tsx:1:3] - 1 │ a && b ? 1 : 2 - · ── ─────── - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of && with ?: - ╭─[no_mixed_operators.tsx:1:2] - 1 │ x ? a && b : 0 - · ───────────── - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of && with ?: - ╭─[no_mixed_operators.tsx:1:2] - 1 │ x ? 0 : a && b - · ─────── ── - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of + with ?? - ╭─[no_mixed_operators.tsx:1:3] - 1 │ a + b ?? c - · ▲ ── - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of in with ?? - ╭─[no_mixed_operators.tsx:1:3] - 1 │ a in b ?? c - · ── ── - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of / with - - ╭─[no_mixed_operators.tsx:1:13] - 1 │ var y = 1.0 - 1/65536.0; - · ▲ ▲ - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of / with - - ╭─[no_mixed_operators.tsx:1:13] - 1 │ var y = 1.0 - 1 /65536.0; - · ▲ ▲ - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of / with - - ╭─[no_mixed_operators.tsx:1:13] - 1 │ var y = 1.0 - 1/ 65536.0; - · ▲ ▲ - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of / with - - ╭─[no_mixed_operators.tsx:1:12] - 1 │ var y = 1.0- 1 / 65536.0; - · ▲ ▲ - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of / with - - ╭─[no_mixed_operators.tsx:1:13] - 1 │ var y = 1.0 -1 / 65536.0; - · ▲ ▲ - ╰──── - help: Use parentheses to clarify the intended order of operations. - - ⚠ eslint(no-mixed-operators): Unexpected mix of / with - - ╭─[no_mixed_operators.tsx:1:12] - 1 │ var y = 1.0-1 / 65536.0; - · ▲ ▲ - ╰──── - help: Use parentheses to clarify the intended order of operations. diff --git a/crates/oxc_linter/src/snapshots/no_return_await.snap b/crates/oxc_linter/src/snapshots/no_return_await.snap deleted file mode 100644 index 66f477f2a..000000000 --- a/crates/oxc_linter/src/snapshots/no_return_await.snap +++ /dev/null @@ -1,302 +0,0 @@ ---- -source: crates/oxc_linter/src/tester.rs -expression: no_return_await ---- - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:9] - 2 │ async function foo() { - 3 │ return await bar(); - · ───── - 4 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:9] - 2 │ async function foo() { - 3 │ return await(bar()); - · ───── - 4 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:13] - 2 │ async function foo() { - 3 │ return (a, await bar()); - · ───── - 4 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:16] - 2 │ async function foo() { - 3 │ return (a, b, await bar()); - · ───── - 4 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:15] - 2 │ async function foo() { - 3 │ return (a && await bar()); - · ───── - 4 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:20] - 2 │ async function foo() { - 3 │ return (a && b && await bar()); - · ───── - 4 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:15] - 2 │ async function foo() { - 3 │ return (a || await bar()); - · ───── - 4 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:23] - 2 │ async function foo() { - 3 │ return (a, b, (c, d, await bar())); - · ───── - 4 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:22] - 2 │ async function foo() { - 3 │ return (a, b, (c && await bar())); - · ───── - 4 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:26] - 2 │ async function foo() { - 3 │ return (await baz(), b, await bar()); - · ───── - 4 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:18] - 2 │ async function foo() { - 3 │ return (baz() ? await bar() : b); - · ───── - 4 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:22] - 2 │ async function foo() { - 3 │ return (baz() ? a : await bar()); - · ───── - 4 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:22] - 2 │ async function foo() { - 3 │ return (baz() ? (a, await bar()) : b); - · ───── - 4 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:26] - 2 │ async function foo() { - 3 │ return (baz() ? a : (b, await bar())); - · ───── - 4 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:24] - 2 │ async function foo() { - 3 │ return (baz() ? (a && await bar()) : b); - · ───── - 4 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:28] - 2 │ async function foo() { - 3 │ return (baz() ? a : (b && await bar())); - · ───── - 4 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:2:22] - 1 │ - 2 │ async () => { return await bar(); } - · ───── - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:2:13] - 1 │ - 2 │ async () => await bar() - · ───── - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:2:20] - 1 │ - 2 │ async () => (a, b, await bar()) - · ───── - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:2:19] - 1 │ - 2 │ async () => (a && await bar()) - · ───── - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:2:22] - 1 │ - 2 │ async () => (baz() ? await bar() : b) - · ───── - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:2:30] - 1 │ - 2 │ async () => (baz() ? a : (b, await bar())) - · ───── - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:2:32] - 1 │ - 2 │ async () => (baz() ? a : (b && await bar())) - · ───── - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:5:11] - 4 │ if (b) { - 5 │ return await bar(); - · ───── - 6 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:5:11] - 4 │ if (b) { - 5 │ return await bar(); - · ───── - 6 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:4:8] - 3 │ finally { - 4 │ return await bar(); - · ───── - 5 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:4:8] - 3 │ finally { - 4 │ return await bar(); - · ───── - 5 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:5:8] - 4 │ catch (e) { - 5 │ return await bar(); - · ───── - 6 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:4:8] - 3 │ async function foo() { - 4 │ return await bar(); - · ───── - 5 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:13] - 2 │ try { - 3 │ async () => await bar(); - · ───── - 4 │ } catch (e) {} - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:7:9] - 6 │ catch (e) { - 7 │ return await bar(); - · ───── - 8 │ } - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:8] - 2 │ async function foo() { - 3 │ return await new Promise(resolve => { - · ───── - 4 │ resolve(5); - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:8] - 2 │ async () => { - 3 │ return await ( - · ───── - 4 │ foo() - ╰──── - help: Remove redundant `await`. - - ⚠ eslint(no-return-await): Redundant use of `await` on a return value. - ╭─[no_return_await.tsx:3:8] - 2 │ async function foo() { - 3 │ return await // Test - · ───── - 4 │ 5; - ╰──── - help: Remove redundant `await`.