feat(linter): remove deprecated eslint v9 rules no-return-await and no-mixed-operators (#3188)

This commit is contained in:
Boshen 2024-05-07 17:17:31 +08:00 committed by GitHub
parent ca9f13f4f2
commit 4defe37f12
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 0 additions and 1101 deletions

View file

@ -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,

View file

@ -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<NoMixedOperatorsConfig>);
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct NoMixedOperatorsConfig {
/// Disallow Mixed operators within one group.
groups: Vec<Vec<&'static str>>,
/// 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 developers 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<Self> {
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<Vec<&'static str>> {
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);
}
}

View file

@ -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();
}

View file

@ -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.

View file

@ -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`.