Skip to content

Commit a82a1f2

Browse files
authored
fix(lint/noUselessEscapeInString): flag useless escapes after skipping \${ in template literals (#6044)
1 parent a743463 commit a82a1f2

File tree

6 files changed

+72
-16
lines changed

6 files changed

+72
-16
lines changed

.changeset/petite-rats-sniff.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@biomejs/biome": patch
3+
---
4+
5+
Fixed [#6042](https://github.com/biomejs/biome/pull/6042): [`noUselessEscapeInString`](https://next.biomejs.dev/linter/rules/no-useless-escape-in-string/) now reports useless escapes after skipping \${ in template literals.

crates/biome_js_analyze/src/lint/nursery/no_useless_escape_in_string.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,13 @@ fn next_useless_escape(str: &str, quote: u8) -> Option<usize> {
165165
| b'u'
166166
| b'v'
167167
| b'x' => {}
168+
// In template literals, \${ is a valid escape for producing a literal ${
169+
b'$' => {
170+
// Clone iterator to peek ahead without advancing, so other escapes like \${\a aren't missed
171+
if !(quote == b'`' && (matches!(it.clone().next(), Some((_, b'{'))))) {
172+
return Some(i);
173+
}
174+
}
168175
// Preserve escaping of Unicode characters U+2028 and U+2029
169176
0xE2 => {
170177
if !(matches!(it.next(), Some((_, 0x80)))
@@ -174,10 +181,6 @@ fn next_useless_escape(str: &str, quote: u8) -> Option<usize> {
174181
}
175182
}
176183
_ => {
177-
// In template literals, \${ is a valid escape for producing a literal ${
178-
if quote == b'`' && c == b'$' && (matches!(it.next(), Some((_, b'{')))) {
179-
return None;
180-
}
181184
// The quote can be escaped
182185
if c != quote {
183186
return Some(i);

crates/biome_js_analyze/tests/specs/nursery/noUselessEscapeInString/invalid.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,7 @@ var s = {
55
// A test with unicode characters that take more than one byte
66
key: "😀\😀",
77
// https://github.com/biomejs/biome/issues/6039
8-
templateLiterals: `\$x`
8+
templateLiterals1: `\$x`,
9+
templateLiterals2: `\${\a`,
10+
templateLiterals3: `\${} \a`
911
};

crates/biome_js_analyze/tests/specs/nursery/noUselessEscapeInString/invalid.js.snap

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ var s = {
1212
// A test with unicode characters that take more than one byte
1313
key: "😀\😀",
1414
// https://github.com/biomejs/biome/issues/6039
15-
templateLiterals: `\$x`
15+
templateLiterals1: `\$x`,
16+
templateLiterals2: `\${\a`,
17+
templateLiterals3: `\${} \a`
1618
};
1719
1820
```
@@ -157,7 +159,7 @@ invalid.js:6:13 lint/nursery/noUselessEscapeInString FIXABLE ━━━━━
157159
> 6 │ key: "😀\😀",
158160
│ ^^
159161
7 │ // https://github.com/biomejs/biome/issues/6039
160-
8 │ templateLiterals: `\$x`
162+
8 │ templateLiterals1: `\$x`,
161163
162164
i Only quotes that enclose the string and special characters need to be escaped.
163165
@@ -169,22 +171,64 @@ invalid.js:6:13 lint/nursery/noUselessEscapeInString FIXABLE ━━━━━
169171
```
170172
171173
```
172-
invalid.js:8:25 lint/nursery/noUselessEscapeInString FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
174+
invalid.js:8:26 lint/nursery/noUselessEscapeInString FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
173175
174176
! The character doesn't need to be escaped.
175177
176178
6key: "😀\😀",
177179
7 │ // https://github.com/biomejs/biome/issues/6039
178-
> 8 │ templateLiterals: `\$x`
179-
^
180-
9};
181-
10
180+
> 8 │ templateLiterals1: `\$x`,
181+
^
182+
9 │ templateLiterals2: `\${\a`,
183+
10 │ templateLiterals3: `\${} \a`
182184
183185
i Only quotes that enclose the string and special characters need to be escaped.
184186
185187
i Safe fix: Unescape the character.
186188
187-
8 │ ····templateLiterals`\$x`
188-
-
189+
8 │ ····templateLiterals1:·`\$x`,
190+
│ -
191+
192+
```
193+
194+
```
195+
invalid.js:9:29 lint/nursery/noUselessEscapeInString FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
196+
197+
! The character doesn't need to be escaped.
198+
199+
7 │ // https://github.com/biomejs/biome/issues/6039
200+
8 │ templateLiterals1: `\$x`,
201+
> 9 │ templateLiterals2: `\${\a`,
202+
│ ^
203+
10 │ templateLiterals3: `\${} \a`
204+
11 │ };
205+
206+
i Only quotes that enclose the string and special characters need to be escaped.
207+
208+
i Safe fix: Unescape the character.
209+
210+
9 │ ····templateLiterals2`\${\a`,
211+
│ -
212+
213+
```
214+
215+
```
216+
invalid.js:10:31 lint/nursery/noUselessEscapeInString FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
217+
218+
! The character doesn't need to be escaped.
219+
220+
8 │ templateLiterals1: `\$x`,
221+
9 │ templateLiterals2: `\${\a`,
222+
> 10 │ templateLiterals3: `\${} \a`
223+
^
224+
11 │ };
225+
12
226+
227+
i Only quotes that enclose the string and special characters need to be escaped.
228+
229+
i Safe fix: Unescape the character.
230+
231+
10 │ ····templateLiterals3`\${}·\a`
232+
-
189233
190234
```

crates/biome_js_analyze/tests/specs/nursery/noUselessEscapeInString/valid.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ var s = {
33
'\0\'': "\n\"",
44
"abc\u42efg": tagged` test ${1} \a`,
55
key: `\``,
6-
escapeTemplateLiteralInterpolation: `\${`
6+
escapeTemplateLiteralInterpolation1: `\${`,
7+
escapeTemplateLiteralInterpolation2: `\${}`
78
};

crates/biome_js_analyze/tests/specs/nursery/noUselessEscapeInString/valid.js.snap

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ var s = {
1010
'\0\'': "\n\"",
1111
"abc\u42efg": tagged` test ${1} \a`,
1212
key: `\``,
13-
escapeTemplateLiteralInterpolation: `\${`
13+
escapeTemplateLiteralInterpolation1: `\${`,
14+
escapeTemplateLiteralInterpolation2: `\${}`
1415
};
1516
1617
```

0 commit comments

Comments
 (0)