mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
refactor(linter): remove all old parse_general_jest_fn_call in jest rules (#1232)
This commit is contained in:
parent
9c0aafcd1c
commit
1dd321e021
8 changed files with 337 additions and 300 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 })
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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', () => {}))
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in a new issue