mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
fix(linter/eslint/no-useless-concat): see through parenthesized expressions (#27984)
Part of #27982 (the `no-useless-concat` half; the `no-unassigned-vars` half is in a separate PR). `get_left` and `get_right` stopped walking at a `ParenthesizedExpression`, so `'a' + ('b')`, `('a') + 'b'`, and the outer `+` in `(foo + 'a') + ('b' + 'c')` were never compared as two string literals. ESTree has no parenthesis nodes, so ESLint flags all of these. Both helpers now call `without_parentheses()` before and while following the `+` chain. ### AI disclosure I used an AI coding assistant to help write this change and its tests. I reviewed the diff and the snapshot output before opening the PR. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Rahul Kashyap <itisrmk@users.noreply.github.com> Co-authored-by: Cameron <cameron.clark@hey.com>
This commit is contained in:
2 files changed
+117
-4
No files matched your search
@@ -84,12 +84,12 @@ impl Rule for NoUselessConcat {
|
||||
}
|
||||
|
||||
fn get_left<'a>(expr: &'a BinaryExpression<'a>) -> &'a Expression<'a> {
|
||||
let mut left = &expr.left;
|
||||
let mut left = expr.left.without_parentheses();
|
||||
loop {
|
||||
if let Expression::BinaryExpression(binary_expr) = left
|
||||
&& binary_expr.operator == BinaryOperator::Addition
|
||||
{
|
||||
left = &binary_expr.right;
|
||||
left = binary_expr.right.without_parentheses();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
@@ -98,12 +98,12 @@ fn get_left<'a>(expr: &'a BinaryExpression<'a>) -> &'a Expression<'a> {
|
||||
}
|
||||
|
||||
fn get_right<'a>(expr: &'a BinaryExpression<'a>) -> &'a Expression<'a> {
|
||||
let mut right = &expr.right;
|
||||
let mut right = expr.right.without_parentheses();
|
||||
loop {
|
||||
if let Expression::BinaryExpression(binary_expr) = right
|
||||
&& binary_expr.operator == BinaryOperator::Addition
|
||||
{
|
||||
right = &binary_expr.left;
|
||||
right = binary_expr.left.without_parentheses();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
@@ -147,6 +147,7 @@ fn test() {
|
||||
"foo['a'] + foo['b']",
|
||||
"`${1 + 1}`",
|
||||
"`${'1' + 1}`",
|
||||
"'a' +\n('b')",
|
||||
];
|
||||
|
||||
let fail = vec![
|
||||
@@ -167,6 +168,15 @@ fn test() {
|
||||
"'a' + 'b' + 'c' + 'd' + 'e' + foo",
|
||||
"`${'a' + 'b'}` + 'c'",
|
||||
"foo['a' + 'b']",
|
||||
"var a = 'a' + ('b');\nvar b = ('a') + 'b';\nvar c = (foo + 'a') + ('b' + 'c');",
|
||||
"'a' + ('b')",
|
||||
"('a') + 'b'",
|
||||
"('a') + ('b')",
|
||||
"((('a'))) + 'b'",
|
||||
"(foo + 'a') + 'b'",
|
||||
"'a' + ('b' + 'c')",
|
||||
"foo + ('a' + 'b')",
|
||||
"'a' + ('b' + foo)",
|
||||
];
|
||||
|
||||
// TODO: Implement a suggestion for this rule.
|
||||
|
||||
@@ -38,6 +38,13 @@ source: crates/oxc_linter/src/tester.rs
|
||||
╰────
|
||||
help: Rewrite into one string literal.
|
||||
|
||||
⚠ eslint(no-useless-concat): Unexpected string concatenation of literals.
|
||||
╭─[no_useless_concat.tsx:1:8]
|
||||
1 │ (foo + 'a') + ('b' + 'c')
|
||||
· ───────────
|
||||
╰────
|
||||
help: Rewrite into one string literal.
|
||||
|
||||
⚠ eslint(no-useless-concat): Unexpected string concatenation of literals.
|
||||
╭─[no_useless_concat.tsx:1:16]
|
||||
1 │ (foo + 'a') + ('b' + 'c')
|
||||
@@ -130,3 +137,99 @@ source: crates/oxc_linter/src/tester.rs
|
||||
· ─────────
|
||||
╰────
|
||||
help: Rewrite into one string literal.
|
||||
|
||||
⚠ eslint(no-useless-concat): Unexpected string concatenation of literals.
|
||||
╭─[no_useless_concat.tsx:1:9]
|
||||
1 │ var a = 'a' + ('b');
|
||||
· ──────────
|
||||
2 │ var b = ('a') + 'b';
|
||||
╰────
|
||||
help: Rewrite into one string literal.
|
||||
|
||||
⚠ eslint(no-useless-concat): Unexpected string concatenation of literals.
|
||||
╭─[no_useless_concat.tsx:2:10]
|
||||
1 │ var a = 'a' + ('b');
|
||||
2 │ var b = ('a') + 'b';
|
||||
· ──────────
|
||||
3 │ var c = (foo + 'a') + ('b' + 'c');
|
||||
╰────
|
||||
help: Rewrite into one string literal.
|
||||
|
||||
⚠ eslint(no-useless-concat): Unexpected string concatenation of literals.
|
||||
╭─[no_useless_concat.tsx:3:16]
|
||||
2 │ var b = ('a') + 'b';
|
||||
3 │ var c = (foo + 'a') + ('b' + 'c');
|
||||
· ───────────
|
||||
╰────
|
||||
help: Rewrite into one string literal.
|
||||
|
||||
⚠ eslint(no-useless-concat): Unexpected string concatenation of literals.
|
||||
╭─[no_useless_concat.tsx:3:24]
|
||||
2 │ var b = ('a') + 'b';
|
||||
3 │ var c = (foo + 'a') + ('b' + 'c');
|
||||
· ─────────
|
||||
╰────
|
||||
help: Rewrite into one string literal.
|
||||
|
||||
⚠ eslint(no-useless-concat): Unexpected string concatenation of literals.
|
||||
╭─[no_useless_concat.tsx:1:1]
|
||||
1 │ 'a' + ('b')
|
||||
· ──────────
|
||||
╰────
|
||||
help: Rewrite into one string literal.
|
||||
|
||||
⚠ eslint(no-useless-concat): Unexpected string concatenation of literals.
|
||||
╭─[no_useless_concat.tsx:1:2]
|
||||
1 │ ('a') + 'b'
|
||||
· ──────────
|
||||
╰────
|
||||
help: Rewrite into one string literal.
|
||||
|
||||
⚠ eslint(no-useless-concat): Unexpected string concatenation of literals.
|
||||
╭─[no_useless_concat.tsx:1:2]
|
||||
1 │ ('a') + ('b')
|
||||
· ───────────
|
||||
╰────
|
||||
help: Rewrite into one string literal.
|
||||
|
||||
⚠ eslint(no-useless-concat): Unexpected string concatenation of literals.
|
||||
╭─[no_useless_concat.tsx:1:4]
|
||||
1 │ ((('a'))) + 'b'
|
||||
· ────────────
|
||||
╰────
|
||||
help: Rewrite into one string literal.
|
||||
|
||||
⚠ eslint(no-useless-concat): Unexpected string concatenation of literals.
|
||||
╭─[no_useless_concat.tsx:1:8]
|
||||
1 │ (foo + 'a') + 'b'
|
||||
· ──────────
|
||||
╰────
|
||||
help: Rewrite into one string literal.
|
||||
|
||||
⚠ eslint(no-useless-concat): Unexpected string concatenation of literals.
|
||||
╭─[no_useless_concat.tsx:1:1]
|
||||
1 │ 'a' + ('b' + 'c')
|
||||
· ──────────
|
||||
╰────
|
||||
help: Rewrite into one string literal.
|
||||
|
||||
⚠ eslint(no-useless-concat): Unexpected string concatenation of literals.
|
||||
╭─[no_useless_concat.tsx:1:8]
|
||||
1 │ 'a' + ('b' + 'c')
|
||||
· ─────────
|
||||
╰────
|
||||
help: Rewrite into one string literal.
|
||||
|
||||
⚠ eslint(no-useless-concat): Unexpected string concatenation of literals.
|
||||
╭─[no_useless_concat.tsx:1:8]
|
||||
1 │ foo + ('a' + 'b')
|
||||
· ─────────
|
||||
╰────
|
||||
help: Rewrite into one string literal.
|
||||
|
||||
⚠ eslint(no-useless-concat): Unexpected string concatenation of literals.
|
||||
╭─[no_useless_concat.tsx:1:1]
|
||||
1 │ 'a' + ('b' + foo)
|
||||
· ──────────
|
||||
╰────
|
||||
help: Rewrite into one string literal.
|
||||
Reference in new issue
Block a user