mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
fix(linter): no-useless-spread fixer with multiple spread elements (#3950)
Closes #3909
This commit is contained in:
parent
ea30aecb67
commit
6498a089ea
1 changed files with 87 additions and 31 deletions
|
|
@ -147,7 +147,10 @@ fn check_useless_spread_in_list<'a>(node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let AstKind::SpreadElement(spread_elem) = parent.kind() {
|
// we're in ...[]
|
||||||
|
let AstKind::SpreadElement(spread_elem) = parent.kind() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
let Some(parent_parent) = outermost_paren_parent(parent, ctx) else {
|
let Some(parent_parent) = outermost_paren_parent(parent, ctx) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
@ -162,13 +165,11 @@ fn check_useless_spread_in_list<'a>(node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AstKind::ArrayExpression(array_expr) => match parent_parent.kind() {
|
AstKind::ArrayExpression(array_expr) => match parent_parent.kind() {
|
||||||
// ...[ ]
|
// ...[ ...[] ]
|
||||||
AstKind::ArrayExpressionElement(_) => {
|
AstKind::ArrayExpressionElement(_) => {
|
||||||
let diagnostic = spread_in_list(span, "array");
|
let diagnostic = spread_in_list(span, "array");
|
||||||
if let Some(outer_array) = ctx.nodes().parent_kind(parent_parent.id()) {
|
if let Some(outer_array) = ctx.nodes().parent_kind(parent_parent.id()) {
|
||||||
ctx.diagnostic_with_fix(diagnostic, |fixer| {
|
diagnose_array_in_array_spread(ctx, diagnostic, &outer_array, array_expr);
|
||||||
fix_replace(fixer, &outer_array, array_expr)
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
ctx.diagnostic(diagnostic);
|
ctx.diagnostic(diagnostic);
|
||||||
}
|
}
|
||||||
|
|
@ -185,6 +186,59 @@ fn check_useless_spread_in_list<'a>(node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `...[ ...[] ]`. May contain multiple spread elements.
|
||||||
|
fn diagnose_array_in_array_spread<'a>(
|
||||||
|
ctx: &LintContext<'a>,
|
||||||
|
diagnostic: OxcDiagnostic,
|
||||||
|
outer_array: &AstKind<'a>,
|
||||||
|
inner_array: &ArrayExpression<'a>,
|
||||||
|
) {
|
||||||
|
let AstKind::ArrayExpression(outer_array) = outer_array else {
|
||||||
|
ctx.diagnostic(diagnostic);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
match outer_array.elements.len() {
|
||||||
|
0 => unreachable!(),
|
||||||
|
1 => {
|
||||||
|
ctx.diagnostic_with_fix(diagnostic, |fixer| {
|
||||||
|
fix_replace(fixer, &outer_array.span, inner_array)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// If all elements are array spreads, we can merge them all together
|
||||||
|
let mut spreads: Vec<&'a ArrayExpression> = vec![];
|
||||||
|
for el in &outer_array.elements {
|
||||||
|
let ArrayExpressionElement::SpreadElement(spread) = el else {
|
||||||
|
ctx.diagnostic(diagnostic);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Expression::ArrayExpression(arr) = &spread.argument else {
|
||||||
|
ctx.diagnostic(diagnostic);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
spreads.push(arr.as_ref());
|
||||||
|
}
|
||||||
|
|
||||||
|
// [ ...[a, b, c], ...[d, e, f] ] -> [a, b, c, d, e, f]
|
||||||
|
ctx.diagnostic_with_fix(diagnostic, |fixer| {
|
||||||
|
let mut codegen = fixer.codegen();
|
||||||
|
codegen.print(b'[');
|
||||||
|
let elements =
|
||||||
|
spreads.iter().flat_map(|arr| arr.elements.iter()).collect::<Vec<_>>();
|
||||||
|
let n = elements.len();
|
||||||
|
for (i, el) in elements.into_iter().enumerate() {
|
||||||
|
codegen.print_expression(el.to_expression());
|
||||||
|
if i < n - 1 {
|
||||||
|
codegen.print(b',');
|
||||||
|
codegen.print_hard_space();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
codegen.print(b']');
|
||||||
|
fixer.replace(outer_array.span, codegen)
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -608,6 +662,8 @@ fn test() {
|
||||||
|
|
||||||
let fix = vec![
|
let fix = vec![
|
||||||
("[...[1,2,3]]", "[1,2,3]"),
|
("[...[1,2,3]]", "[1,2,3]"),
|
||||||
|
("[...[1,2,3], ...[4,5,6]]", "[1, 2, 3, 4, 5, 6]"),
|
||||||
|
("[...[1,2,3], ...x]", "[...[1,2,3], ...x]"),
|
||||||
("[...[...[1,2,3]]]", "[...[1,2,3]]"),
|
("[...[...[1,2,3]]]", "[...[1,2,3]]"),
|
||||||
("[...foo.map(x => !!x)]", "foo.map(x => !!x)"),
|
("[...foo.map(x => !!x)]", "foo.map(x => !!x)"),
|
||||||
(r"[...await Promise.all(foo)]", r"await Promise.all(foo)"),
|
(r"[...await Promise.all(foo)]", r"await Promise.all(foo)"),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue