refactor(linter): remove all old parse_general_jest_fn_call in jest rules (#1232)

This commit is contained in:
Wenzhe Wang 2023-11-12 18:57:30 +08:00 committed by GitHub
parent 9c0aafcd1c
commit 1dd321e021
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 337 additions and 300 deletions

View file

@ -13,16 +13,24 @@ use crate::{
context::LintContext,
rule::Rule,
utils::{
get_node_name, parse_general_jest_fn_call, JestFnKind, JestGeneralFnKind,
ParsedGeneralJestFnCall,
collect_possible_jest_call_node, get_node_name, parse_general_jest_fn_call_new, JestFnKind,
JestGeneralFnKind, PossibleJestNode,
},
AstNode,
};
#[derive(Debug, Error, Diagnostic)]
#[error("eslint-plugin-jest(no-done-callback): {0:?}")]
#[diagnostic(severity(warning), help("{1:?}"))]
struct NoDoneCallbackDiagnostic(&'static str, &'static str, #[label] pub Span);
enum NoDoneCallbackDiagnostic {
#[error("eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument")]
#[diagnostic(
severity(warning),
help("Return a Promise instead of relying on callback parameter")
)]
NoDoneCallback(#[label] Span),
#[error("eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument")]
#[diagnostic(severity(warning), help("Use await instead of callback in async functions"))]
UseAwaitInsteadOfCallback(#[label] Span),
}
#[derive(Debug, Default, Clone)]
pub struct NoDoneCallback;
@ -74,74 +82,78 @@ declare_oxc_lint!(
);
impl Rule for NoDoneCallback {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
if let AstKind::CallExpression(call_expr) = node.kind() {
if let Some(jest_fn_call) = parse_general_jest_fn_call(call_expr, node, ctx) {
let ParsedGeneralJestFnCall { kind, .. } = jest_fn_call;
if !matches!(
kind,
JestFnKind::General(JestGeneralFnKind::Test | JestGeneralFnKind::Hook)
) {
return;
}
fn run_once(&self, ctx: &LintContext) {
for node in &collect_possible_jest_call_node(ctx) {
run(node, ctx);
}
}
}
let is_jest_each = get_node_name(&call_expr.callee).ends_with("each");
fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) {
let node = possible_jest_node.node;
if let AstKind::CallExpression(call_expr) = node.kind() {
if let Some(jest_fn_call) =
parse_general_jest_fn_call_new(call_expr, possible_jest_node, ctx)
{
let kind = jest_fn_call.kind;
if !matches!(
kind,
JestFnKind::General(JestGeneralFnKind::Test | JestGeneralFnKind::Hook)
) {
return;
}
if is_jest_each
&& !matches!(call_expr.callee, Expression::TaggedTemplateExpression(_))
{
// isJestEach but not a TaggedTemplateExpression, so this must be
// the `jest.each([])()` syntax which this rule doesn't support due
// to its complexity (see jest-community/eslint-plugin-jest#710)
return;
}
let is_jest_each = get_node_name(&call_expr.callee).ends_with("each");
let Some(Argument::Expression(expr)) =
find_argument_of_callback(call_expr, is_jest_each, kind)
else {
return;
};
if is_jest_each && !matches!(call_expr.callee, Expression::TaggedTemplateExpression(_))
{
// isJestEach but not a TaggedTemplateExpression, so this must be
// the `jest.each([])()` syntax which this rule doesn't support due
// to its complexity (see jest-community/eslint-plugin-jest#710)
return;
}
let callback_arg_index = usize::from(is_jest_each);
let Some(Argument::Expression(expr)) =
find_argument_of_callback(call_expr, is_jest_each, kind)
else {
return;
};
match expr {
Expression::FunctionExpression(func_expr) => {
if func_expr.params.parameters_count() != 1 + callback_arg_index {
return;
}
let Some(span) = get_span_of_first_parameter(&func_expr.params) else {
return;
};
let callback_arg_index = usize::from(is_jest_each);
if func_expr.r#async {
let (message, help) = Message::UseAwaitInsteadOfCallback.details();
ctx.diagnostic(NoDoneCallbackDiagnostic(message, help, span));
return;
}
let (message, help) = Message::NoDoneCallback.details();
ctx.diagnostic(NoDoneCallbackDiagnostic(message, help, span));
match expr {
Expression::FunctionExpression(func_expr) => {
if func_expr.params.parameters_count() != 1 + callback_arg_index {
return;
}
Expression::ArrowExpression(arrow_expr) => {
if arrow_expr.params.parameters_count() != 1 + callback_arg_index {
return;
}
let Some(span) = get_span_of_first_parameter(&func_expr.params) else {
return;
};
let Some(span) = get_span_of_first_parameter(&arrow_expr.params) else {
return;
};
if arrow_expr.r#async {
let (message, help) = Message::UseAwaitInsteadOfCallback.details();
ctx.diagnostic(NoDoneCallbackDiagnostic(message, help, span));
return;
}
let (message, help) = Message::NoDoneCallback.details();
ctx.diagnostic(NoDoneCallbackDiagnostic(message, help, span));
if func_expr.r#async {
ctx.diagnostic(NoDoneCallbackDiagnostic::UseAwaitInsteadOfCallback(span));
return;
}
_ => {}
ctx.diagnostic(NoDoneCallbackDiagnostic::NoDoneCallback(span));
}
Expression::ArrowExpression(arrow_expr) => {
if arrow_expr.params.parameters_count() != 1 + callback_arg_index {
return;
}
let Some(span) = get_span_of_first_parameter(&arrow_expr.params) else {
return;
};
if arrow_expr.r#async {
ctx.diagnostic(NoDoneCallbackDiagnostic::UseAwaitInsteadOfCallback(span));
return;
}
ctx.diagnostic(NoDoneCallbackDiagnostic::NoDoneCallback(span));
}
_ => {}
}
}
}
@ -176,26 +188,6 @@ fn find_argument_of_callback<'a>(
None
}
enum Message {
NoDoneCallback,
UseAwaitInsteadOfCallback,
}
impl Message {
fn details(&self) -> (&'static str, &'static str) {
match self {
Self::NoDoneCallback => (
"Function parameter(s) use the `done` argument",
"Return a Promise instead of relying on callback parameter",
),
Self::UseAwaitInsteadOfCallback => (
"Function parameter(s) use the `done` argument",
"Use await instead of callback in async functions",
),
}
}
}
#[test]
fn test() {
use crate::tester::Tester;

View file

@ -11,10 +11,10 @@ use crate::{
fixer::Fix,
rule::Rule,
utils::{
parse_general_jest_fn_call, JestFnKind, JestGeneralFnKind, MemberExpressionElement,
ParsedGeneralJestFnCall,
collect_possible_jest_call_node, parse_general_jest_fn_call_new, JestFnKind,
JestGeneralFnKind, MemberExpressionElementNew, ParsedGeneralJestFnCallNew,
PossibleJestNode,
},
AstNode,
};
#[derive(Debug, Error, Diagnostic)]
@ -58,39 +58,46 @@ declare_oxc_lint!(
);
impl Rule for NoFocusedTests {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
let AstKind::CallExpression(call_expr) = node.kind() else { return };
let Some(jest_fn_call) = parse_general_jest_fn_call(call_expr, node, ctx) else { return };
let ParsedGeneralJestFnCall { kind, members, name } = jest_fn_call;
if !matches!(
kind,
JestFnKind::General(JestGeneralFnKind::Describe | JestGeneralFnKind::Test)
) {
return;
fn run_once(&self, ctx: &LintContext) {
for node in &collect_possible_jest_call_node(ctx) {
run(node, ctx);
}
}
}
if name.starts_with('f') {
ctx.diagnostic_with_fix(NoFocusedTestsDiagnostic(call_expr.span), || {
let start = call_expr.span.start;
Fix::delete(Span { start, end: start + 1 })
});
fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) {
let node = possible_jest_node.node;
let AstKind::CallExpression(call_expr) = node.kind() else { return };
let Some(jest_fn_call) = parse_general_jest_fn_call_new(call_expr, possible_jest_node, ctx)
else {
return;
};
let ParsedGeneralJestFnCallNew { kind, members, name } = jest_fn_call;
if !matches!(kind, JestFnKind::General(JestGeneralFnKind::Describe | JestGeneralFnKind::Test)) {
return;
}
return;
}
if name.starts_with('f') {
ctx.diagnostic_with_fix(NoFocusedTestsDiagnostic(call_expr.span), || {
let start = call_expr.span.start;
Fix::delete(Span { start, end: start + 1 })
});
let only_node = members.iter().find(|member| member.is_name_equal("only"));
if let Some(only_node) = only_node {
ctx.diagnostic_with_fix(NoFocusedTestsDiagnostic(call_expr.span), || {
let span = only_node.span;
let start = span.start - 1;
let end = if matches!(only_node.element, MemberExpressionElement::IdentName(_)) {
span.end
} else {
span.end + 1
};
Fix::delete(Span { start, end })
});
}
return;
}
let only_node = members.iter().find(|member| member.is_name_equal("only"));
if let Some(only_node) = only_node {
ctx.diagnostic_with_fix(NoFocusedTestsDiagnostic(call_expr.span), || {
let span = only_node.span;
let start = span.start - 1;
let end = if matches!(only_node.element, MemberExpressionElementNew::IdentName(_)) {
span.end
} else {
span.end + 1
};
Fix::delete(Span { start, end })
});
}
}

View file

@ -11,10 +11,9 @@ use crate::{
fixer::Fix,
rule::Rule,
utils::{
parse_general_jest_fn_call, JestGeneralFnKind, KnownMemberExpressionProperty,
ParsedGeneralJestFnCall,
collect_possible_jest_call_node, parse_general_jest_fn_call_new, JestGeneralFnKind,
KnownMemberExpressionPropertyNew, ParsedGeneralJestFnCallNew, PossibleJestNode,
},
AstNode,
};
#[derive(Debug, Error, Diagnostic)]
@ -51,13 +50,55 @@ declare_oxc_lint!(
style
);
fn get_preferred_node_names(jest_fn_call: &ParsedGeneralJestFnCall) -> Atom {
let ParsedGeneralJestFnCall { members, name, .. } = jest_fn_call;
impl Rule for NoTestPrefixes {
fn run_once(&self, ctx: &LintContext) {
for node in &collect_possible_jest_call_node(ctx) {
run(node, ctx);
}
}
}
fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) {
let node = possible_jest_node.node;
let AstKind::CallExpression(call_expr) = node.kind() else { return };
let Some(jest_fn_call) = parse_general_jest_fn_call_new(call_expr, possible_jest_node, ctx)
else {
return;
};
let ParsedGeneralJestFnCallNew { kind, name, .. } = &jest_fn_call;
let Some(kind) = kind.to_general() else { return };
if !matches!(kind, JestGeneralFnKind::Describe | JestGeneralFnKind::Test) {
return;
}
if !name.starts_with('f') && !name.starts_with('x') {
return;
}
let span = match &call_expr.callee {
Expression::TaggedTemplateExpression(tagged_template_expr) => {
tagged_template_expr.tag.span()
}
Expression::CallExpression(child_call_expr) => child_call_expr.callee.span(),
_ => call_expr.callee.span(),
};
let preferred_node_name = get_preferred_node_names(&jest_fn_call);
let preferred_node_name_cloned = preferred_node_name.clone();
ctx.diagnostic_with_fix(NoTestPrefixesDiagnostic(preferred_node_name, span), || {
Fix::new(preferred_node_name_cloned.to_string(), span)
});
}
fn get_preferred_node_names(jest_fn_call: &ParsedGeneralJestFnCallNew) -> Atom {
let ParsedGeneralJestFnCallNew { members, name, .. } = jest_fn_call;
let preferred_modifier = if name.starts_with('f') { "only" } else { "skip" };
let member_names = members
.iter()
.filter_map(KnownMemberExpressionProperty::name)
.filter_map(KnownMemberExpressionPropertyNew::name)
.collect::<Vec<_>>()
.join(".");
let name_slice = &name[1..];
@ -69,38 +110,6 @@ fn get_preferred_node_names(jest_fn_call: &ParsedGeneralJestFnCall) -> Atom {
}
}
impl Rule for NoTestPrefixes {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
let AstKind::CallExpression(call_expr) = node.kind() else { return };
let Some(jest_fn_call) = parse_general_jest_fn_call(call_expr, node, ctx) else { return };
let ParsedGeneralJestFnCall { kind, name, .. } = &jest_fn_call;
let Some(kind) = kind.to_general() else { return };
if !matches!(kind, JestGeneralFnKind::Describe | JestGeneralFnKind::Test) {
return;
}
if !name.starts_with('f') && !name.starts_with('x') {
return;
}
let span = match &call_expr.callee {
Expression::TaggedTemplateExpression(tagged_template_expr) => {
tagged_template_expr.tag.span()
}
Expression::CallExpression(child_call_expr) => child_call_expr.callee.span(),
_ => call_expr.callee.span(),
};
let preferred_node_name = get_preferred_node_names(&jest_fn_call);
let preferred_node_name_cloned = preferred_node_name.clone();
ctx.diagnostic_with_fix(NoTestPrefixesDiagnostic(preferred_node_name, span), || {
Fix::new(preferred_node_name_cloned.to_string(), span)
});
}
}
#[test]
fn test() {
use crate::tester::Tester;

View file

@ -12,8 +12,10 @@ use oxc_span::{GetSpan, Span};
use crate::{
context::LintContext,
rule::Rule,
utils::{parse_general_jest_fn_call, JestFnKind, JestGeneralFnKind},
AstNode,
utils::{
collect_possible_jest_call_node, parse_general_jest_fn_call_new, JestFnKind,
JestGeneralFnKind, PossibleJestNode,
},
};
#[derive(Debug, Error, Diagnostic)]
@ -63,73 +65,83 @@ declare_oxc_lint!(
);
impl Rule for ValidDescribeCallback {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
let AstKind::CallExpression(call_expr) = node.kind() else { return };
let Some(jest_fn_call) = parse_general_jest_fn_call(call_expr, node, ctx) else { return };
if !matches!(jest_fn_call.kind, JestFnKind::General(JestGeneralFnKind::Describe)) {
return;
fn run_once(&self, ctx: &LintContext) {
for node in &collect_possible_jest_call_node(ctx) {
run(node, ctx);
}
}
}
if call_expr.arguments.len() == 0 {
diagnostic(ctx, call_expr.span, Message::NameAndCallback);
return;
}
fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) {
let node = possible_jest_node.node;
let AstKind::CallExpression(call_expr) = node.kind() else { return };
let Some(jest_fn_call) = parse_general_jest_fn_call_new(call_expr, possible_jest_node, ctx)
else {
return;
};
if !matches!(jest_fn_call.kind, JestFnKind::General(JestGeneralFnKind::Describe)) {
return;
}
if call_expr.arguments.len() == 1 {
// For better error notice, we locate it to arguments[0]
diagnostic(ctx, call_expr.arguments[0].span(), Message::NameAndCallback);
return;
}
if call_expr.arguments.len() == 0 {
diagnostic(ctx, call_expr.span, Message::NameAndCallback);
return;
}
let callback = &call_expr.arguments[1];
match callback {
Argument::Expression(expr) => match expr {
Expression::FunctionExpression(fn_expr) => {
if fn_expr.r#async {
diagnostic(ctx, fn_expr.span, Message::NoAsyncDescribeCallback);
}
let no_each_fields =
jest_fn_call.members.iter().all(|member| member.is_name_unequal("each"));
if no_each_fields && fn_expr.params.parameters_count() > 0 {
diagnostic(ctx, fn_expr.span, Message::UnexpectedDescribeArgument);
}
if call_expr.arguments.len() == 1 {
// For better error notice, we locate it to arguments[0]
diagnostic(ctx, call_expr.arguments[0].span(), Message::NameAndCallback);
return;
}
let Some(ref body) = fn_expr.body else {
let callback = &call_expr.arguments[1];
match callback {
Argument::Expression(expr) => match expr {
Expression::FunctionExpression(fn_expr) => {
if fn_expr.r#async {
diagnostic(ctx, fn_expr.span, Message::NoAsyncDescribeCallback);
}
let no_each_fields =
jest_fn_call.members.iter().all(|member| member.is_name_unequal("each"));
if no_each_fields && fn_expr.params.parameters_count() > 0 {
diagnostic(ctx, fn_expr.span, Message::UnexpectedDescribeArgument);
}
let Some(ref body) = fn_expr.body else {
return;
};
if let Some(span) = find_first_return_stmt_span(body) {
diagnostic(ctx, span, Message::UnexpectedReturnInDescribe);
}
}
Expression::ArrowExpression(arrow_expr) => {
if arrow_expr.r#async {
diagnostic(ctx, arrow_expr.span, Message::NoAsyncDescribeCallback);
}
let no_each_fields =
jest_fn_call.members.iter().all(|member| member.is_name_unequal("each"));
if no_each_fields && arrow_expr.params.parameters_count() > 0 {
diagnostic(ctx, arrow_expr.span, Message::UnexpectedDescribeArgument);
}
if arrow_expr.expression && arrow_expr.body.statements.len() > 0 {
let stmt = &arrow_expr.body.statements[0];
let Statement::ExpressionStatement(expr_stmt) = stmt else {
return;
};
if let Some(span) = find_first_return_stmt_span(body) {
diagnostic(ctx, span, Message::UnexpectedReturnInDescribe);
if let Expression::CallExpression(call_expr) = &expr_stmt.expression {
diagnostic(ctx, call_expr.span, Message::UnexpectedReturnInDescribe);
}
}
Expression::ArrowExpression(arrow_expr) => {
if arrow_expr.r#async {
diagnostic(ctx, arrow_expr.span, Message::NoAsyncDescribeCallback);
}
let no_each_fields =
jest_fn_call.members.iter().all(|member| member.is_name_unequal("each"));
if no_each_fields && arrow_expr.params.parameters_count() > 0 {
diagnostic(ctx, arrow_expr.span, Message::UnexpectedDescribeArgument);
}
if arrow_expr.expression && arrow_expr.body.statements.len() > 0 {
let stmt = &arrow_expr.body.statements[0];
let Statement::ExpressionStatement(expr_stmt) = stmt else {
return;
};
if let Expression::CallExpression(call_expr) = &expr_stmt.expression {
diagnostic(ctx, call_expr.span, Message::UnexpectedReturnInDescribe);
}
}
if let Some(span) = find_first_return_stmt_span(&arrow_expr.body) {
diagnostic(ctx, span, Message::UnexpectedReturnInDescribe);
}
if let Some(span) = find_first_return_stmt_span(&arrow_expr.body) {
diagnostic(ctx, span, Message::UnexpectedReturnInDescribe);
}
_ => diagnostic(ctx, expr.span(), Message::SecondArgumentMustBeFunction),
},
Argument::SpreadElement(spreed_element) => {
diagnostic(ctx, spreed_element.span, Message::SecondArgumentMustBeFunction);
}
_ => diagnostic(ctx, expr.span(), Message::SecondArgumentMustBeFunction),
},
Argument::SpreadElement(spreed_element) => {
diagnostic(ctx, spreed_element.span, Message::SecondArgumentMustBeFunction);
}
}
}

View file

@ -15,8 +15,10 @@ use regex::Regex;
use crate::{
context::LintContext,
rule::Rule,
utils::{parse_general_jest_fn_call, JestFnKind, JestGeneralFnKind},
AstNode,
utils::{
collect_possible_jest_call_node, parse_general_jest_fn_call_new, JestFnKind,
JestGeneralFnKind, PossibleJestNode,
},
};
#[derive(Debug, Error, Diagnostic)]
@ -94,11 +96,23 @@ impl Rule for ValidTitle {
must_match_patterns,
}
}
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
fn run_once(&self, ctx: &LintContext) {
for node in &collect_possible_jest_call_node(ctx) {
self.run(node, ctx);
}
}
}
impl ValidTitle {
fn run<'a>(&self, possible_jest_fn_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) {
let node = possible_jest_fn_node.node;
let AstKind::CallExpression(call_expr) = node.kind() else {
return;
};
let Some(jest_fn_call) = parse_general_jest_fn_call(call_expr, node, ctx) else {
let Some(jest_fn_call) =
parse_general_jest_fn_call_new(call_expr, possible_jest_fn_node, ctx)
else {
return;
};

View file

@ -2,233 +2,233 @@
source: crates/oxc_linter/src/tester.rs
expression: no_done_callback
---
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ test('something', (...args) => {args[0]();})
· ───────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ test('something', done => {done();})
· ────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ test('something', (done,) => {done();})
· ────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ test('something', finished => {finished();})
· ────────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ test('something', (done) => {done();})
· ────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ test('something', done => done())
· ────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ test('something', (done) => done())
· ────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ test('something', function(done) {done();})
· ────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ test('something', function (done) {done();})
· ────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ test('something', async done => {done();})
· ────
╰────
help: "Use await instead of callback in async functions"
help: Use await instead of callback in async functions
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ test('something', async done => done())
· ────
╰────
help: "Use await instead of callback in async functions"
help: Use await instead of callback in async functions
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ test('something', async function (done) {done();})
· ────
╰────
help: "Use await instead of callback in async functions"
help: Use await instead of callback in async functions
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │
2 │ test('my test', async (done) => {
· ────
3 │ await myAsyncTask();
╰────
help: "Use await instead of callback in async functions"
help: Use await instead of callback in async functions
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │
2 │ test('something', (done) => {
· ────
3 │ done();
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ afterEach((...args) => {args[0]();})
· ───────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ beforeAll(done => {done();})
· ────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ beforeAll(finished => {finished();})
· ────────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ beforeEach((done) => {done();})
· ────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ afterAll(done => done())
· ────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ afterEach((done) => done())
· ────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ beforeAll(function(done) {done();})
· ────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ afterEach(function (done) {done();})
· ────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ beforeAll(async done => {done();})
· ────
╰────
help: "Use await instead of callback in async functions"
help: Use await instead of callback in async functions
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ beforeAll(async done => done())
· ────
╰────
help: "Use await instead of callback in async functions"
help: Use await instead of callback in async functions
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ beforeAll(async function (done) {done();})
· ────
╰────
help: "Use await instead of callback in async functions"
help: Use await instead of callback in async functions
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │
2 │ afterAll(async (done) => {
· ────
3 │ await myAsyncTask();
╰────
help: "Use await instead of callback in async functions"
help: Use await instead of callback in async functions
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │
2 │ beforeEach((done) => {
· ────
3 │ done();
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:3:1]
3 │
4 │ beforeEach((done) => {
· ────
5 │ done();
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:3:1]
3 │
4 │ atTheStartOfEachTest((done) => {
· ────
5 │ done();
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ test.each``('something', ({ a, b }, done) => { done(); })
· ────────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter
⚠ eslint-plugin-jest(no-done-callback): "Function parameter(s) use the `done` argument"
⚠ eslint-plugin-jest(no-done-callback): Function parameter(s) use the `done` argument
╭─[no_done_callback.tsx:1:1]
1 │ it.each``('something', ({ a, b }, done) => { done(); })
· ────────
╰────
help: "Return a Promise instead of relying on callback parameter"
help: Return a Promise instead of relying on callback parameter

View file

@ -162,6 +162,18 @@ expression: valid_describe_callback
╰────
help: "Remove return statement in your describe callback"
⚠ eslint-plugin-jest(valid-describe-callback): "Unexpected return statement in describe callback"
╭─[valid_describe_callback.tsx:8:1]
8 │ describe('nested', () => {
9 │ ╭─▶ return Promise.resolve().then(() => {
10 │ │ it('breaks', () => {
11 │ │ throw new Error('Fail')
12 │ │ })
13 │ ╰─▶ })
14 │ })
╰────
help: "Remove return statement in your describe callback"
⚠ eslint-plugin-jest(valid-describe-callback): "Unexpected return statement in describe callback"
╭─[valid_describe_callback.tsx:2:1]
2 │ describe('foo', () => {
@ -175,14 +187,14 @@ expression: valid_describe_callback
help: "Remove return statement in your describe callback"
⚠ eslint-plugin-jest(valid-describe-callback): "Unexpected return statement in describe callback"
╭─[valid_describe_callback.tsx:8:1]
8 │ describe('nested', () => {
9 │ ╭─▶ return Promise.resolve().then(() => {
10 │ │ it('breaks', () => {
11 │ │ throw new Error('Fail')
12 │ │ })
13 │ ╰─▶ })
14 │ })
╭─[valid_describe_callback.tsx:5:1]
5 │ describe('nested', () => {
6 │ ╭─▶ return Promise.resolve().then(() => {
7 │ │ it('breaks', () => {
8 │ │ throw new Error('Fail')
9 │ │ })
10 │ ╰─▶ })
11 │ })
╰────
help: "Remove return statement in your describe callback"
@ -204,18 +216,6 @@ expression: valid_describe_callback
╰────
help: "Remove `async` keyword"
⚠ eslint-plugin-jest(valid-describe-callback): "Unexpected return statement in describe callback"
╭─[valid_describe_callback.tsx:5:1]
5 │ describe('nested', () => {
6 │ ╭─▶ return Promise.resolve().then(() => {
7 │ │ it('breaks', () => {
8 │ │ throw new Error('Fail')
9 │ │ })
10 │ ╰─▶ })
11 │ })
╰────
help: "Remove return statement in your describe callback"
⚠ eslint-plugin-jest(valid-describe-callback): "Unexpected return statement in describe callback"
╭─[valid_describe_callback.tsx:1:1]
1 │ describe('foo', () => test('bar', () => {}))

View file

@ -26,6 +26,8 @@ mod parse_jest_fn_new;
pub use crate::utils::jest::parse_jest_fn_new::{
parse_jest_fn_call as parse_jest_fn_call_new,
KnownMemberExpressionParentKind as KnownMemberExpressionParentKindNew,
KnownMemberExpressionProperty as KnownMemberExpressionPropertyNew,
MemberExpressionElement as MemberExpressionElementNew,
ParsedExpectFnCall as ParsedExpectFnCallNew,
ParsedGeneralJestFnCall as ParsedGeneralJestFnCallNew, ParsedJestFnCall as ParsedJestFnCallNew,
};
@ -117,6 +119,7 @@ pub fn is_type_of_jest_fn_call<'a>(
false
}
#[allow(unused)]
pub fn parse_general_jest_fn_call<'a>(
call_expr: &'a CallExpression<'a>,
node: &AstNode<'a>,
@ -201,13 +204,13 @@ pub fn collect_possible_jest_call_node<'a, 'b>(
vec![]
};
// The longest length of Jest chains is 4, e.g.`expect(1).not.resolved.toBe()`.
// We take 4 ancestors of node and collect all Call Expression.
// The longest length of Jest chains is 4, and it may be a TaggedTemplateExpression, e.g.`it.concurrent.only.each``()`.
// We take 5 ancestors of node and collect all Call Expression.
// The invalid Jest Call Expression will be bypassed in `parse_jest_fn_call`
reference_id_with_original_list.iter().fold(vec![], |mut acc, id_with_original| {
let (reference_id, original) = id_with_original;
let mut id = ctx.symbols().get_reference(*reference_id).node_id();
for _ in 0..4 {
for _ in 0..5 {
let parent = ctx.nodes().parent_node(id);
if let Some(parent) = parent {
let parent_kind = parent.kind();