Skip to content

Commit c4cb4d0

Browse files
authored
refactor(noUnusedImports): keep orphan comments (#4479)
1 parent c871e9a commit c4cb4d0

File tree

8 files changed

+211
-124
lines changed

8 files changed

+211
-124
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,19 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b
155155

156156
Contributed by @Conaclos
157157

158+
- `noUnusedImports` now keeps comments separated from the import with a blank line ([#3401](https://github.com/biomejs/biome/issues/3401)).
159+
160+
Here is an example:
161+
162+
```diff
163+
// Orphan comment
164+
165+
- // Header comment
166+
- import {} from "mod";
167+
```
168+
169+
Contributed by @Conaclos
170+
158171
#### Bug fixes
159172

160173
- [useArrayLiterals](https://biomejs.dev/linter/rules/use-array-literals/) now reports all expressions using the `Array` constructors.

crates/biome_js_analyze/src/lint/correctness/no_unused_imports.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,32 @@ impl Rule for NoUnusedImports {
216216
match state {
217217
Unused::EmptyStatement(_) | Unused::AllImports(_) => {
218218
let parent = node.syntax().parent()?;
219+
let leading_trivia = parent.first_leading_trivia()?;
220+
let mut leading_trivia_pieces = leading_trivia.pieces().collect::<Vec<_>>();
221+
let blank_line_pos = leading_trivia_pieces
222+
.windows(2)
223+
.rposition(|window| window[0].is_newline() && window[1].is_newline());
224+
if let Some(blank_line_pos) = blank_line_pos {
225+
// keep all leading trivia until the last blank line.
226+
leading_trivia_pieces.truncate(blank_line_pos + 1);
227+
if let Some(prev_sibling) = parent.prev_sibling() {
228+
let new_prev_sibling = prev_sibling
229+
.clone()
230+
.append_trivia_pieces(leading_trivia_pieces)?;
231+
mutation.replace_element_discard_trivia(
232+
prev_sibling.into(),
233+
new_prev_sibling.into(),
234+
);
235+
} else if let Some(next_sibling) = parent.next_sibling() {
236+
let new_next_sibling = next_sibling
237+
.clone()
238+
.prepend_trivia_pieces(leading_trivia_pieces)?;
239+
mutation.replace_element_discard_trivia(
240+
next_sibling.into(),
241+
new_next_sibling.into(),
242+
);
243+
}
244+
}
219245
mutation.remove_element(parent.into());
220246
}
221247
Unused::DefaultImport(_) => {

crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid-import-namespace.ts.snap

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,11 @@ invalid-import-namespace.ts:4:18 lint/correctness/noUnusedImports FIXABLE ━
4848
i Safe fix: Remove the unused imports.
4949
5050
1 1 │ import * as Ns1 from ""
51-
2 2 │ export type T1 = Ns1;
52-
3 │ -
51+
2 │ - export·type·T1·=·Ns1;
52+
2 │ + export·type·T1·=·Ns1;
53+
3 3 │
5354
4 │ - import·type·*·as·Ns2·from·""
54-
5 3 │ export type T2 = Ns2;
55+
5 4 │ export type T2 = Ns2;
5556
5657
5758
```

crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid-unused-react.jsx.snap

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,14 @@ invalid-unused-react.jsx:5:8 lint/correctness/noUnusedImports FIXABLE ━━
100100
101101
i Safe fix: Remove the unused imports.
102102
103+
1 1 │ import X from "react"
103104
2 2 │ import * as X from "react"
104-
3 3 │ import { default as X } from "react"
105-
4 │ -
105+
3 │ - import·{·default·as·X·}·from·"react"
106+
3 │ + import·{·default·as·X·}·from·"react"
107+
4 4 │
106108
5 │ - import·React·from·"x"
107-
6 4 │ import * as React from "x"
108-
7 5 │ import { default as React } from "x"
109+
6 5 │ import * as React from "x"
110+
7 6 │ import { default as React } from "x"
109111
110112
111113
```

crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.js.snap

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,13 @@ invalid.js:5:13 lint/correctness/noUnusedImports FIXABLE ━━━━━━━
8181
i Safe fix: Remove the unused imports.
8282
8383
1 1 │ // Header comment
84-
2 2 │ import A from "mod";
85-
3 │ -
84+
2 │ - import·A·from·"mod";
85+
2 │ + import·A·from·"mod";
86+
3 3 │
8687
4 │ - //·Header·comment
8788
5 │ - import·*·as·B·from·"mod";·//·Import·comment
88-
6 3
89-
7 4 │ // Header comment
89+
6 4
90+
7 5 │ // Header comment
9091
9192
9293
```
@@ -106,13 +107,15 @@ invalid.js:8:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━
106107
107108
i Safe fix: Remove the unused imports.
108109
110+
3 3 │
109111
4 4 │ // Header comment
110-
5 5 │ import * as B from "mod"; // Import comment
111-
6 │ -
112+
5 │ - import·*·as·B·from·"mod";·//·Import·comment
113+
5 │ + import·*·as·B·from·"mod";·//·Import·comment
114+
6 6 │
112115
7 │ - //·Header·comment
113116
8 │ - import·{·C·}·from·"mod";·//·Import·comment
114-
9 6
115-
10 7 │ // Header comment
117+
9 7
118+
10 8 │ // Header comment
116119
117120
118121
```
@@ -132,13 +135,15 @@ invalid.js:11:14 lint/correctness/noUnusedImports FIXABLE ━━━━━━
132135
133136
i Safe fix: Remove the unused imports.
134137
138+
6 6 │
135139
7 7 │ // Header comment
136-
8 8 │ import { C } from "mod"; // Import comment
137-
9 │ -
140+
8 │ - import·{·C·}·from·"mod";·//·Import·comment
141+
8 │ + import·{·C·}·from·"mod";·//·Import·comment
142+
9 9 │
138143
10 │ - //·Header·comment
139144
11 │ - import·/*a*/·D·/*b*/,·/*c*/{·E·}/*d*/·from·"mod";·//·Import·comment
140-
12 9
141-
13 10 │ import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod";
145+
12 10
146+
13 11 │ import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod";
142147
143148
144149
```
@@ -159,12 +164,14 @@ invalid.js:13:14 lint/correctness/noUnusedImports FIXABLE ━━━━━━
159164
160165
i Safe fix: Remove the unused imports.
161166
167+
9 9
162168
10 10// Header comment
163-
11 11import /*a*/ D /*b*/, /*c*/{ E }/*d*/ from "mod"; // Import comment
164-
12-
169+
11- import·/*a*/·D·/*b*//*c*/{·E·}/*d*/·from·"mod"//·Import·comment
170+
11+ import·/*a*/·D·/*b*//*c*/{·E·}/*d*/·from·"mod"//·Import·comment
171+
12 12
165172
13- import·/*a*/·F·/*b*//*c*/·*·as·G·/*d*/·from·"mod";
166-
14 12
167-
15 13import {
173+
14 13
174+
15 14import {
168175
169176
170177
```
@@ -190,16 +197,18 @@ invalid.js:15:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━
190197
191198
i Safe fix: Remove the unused imports.
192199
200+
11 11import /*a*/ D /*b*/, /*c*/{ E }/*d*/ from "mod"; // Import comment
193201
12 12
194-
13 13import /*a*/ F /*b*/, /*c*/ * as G /*d*/ from "mod";
195-
14-
202+
13- import·/*a*/·F·/*b*//*c*/·*·as·G·/*d*/·from·"mod";
203+
13+ import·/*a*/·F·/*b*//*c*/·*·as·G·/*d*/·from·"mod";
204+
14 14
196205
15- import·{
197206
16 │ - ····//·Comment
198207
17 │ - ····H,
199208
18 │ - ····I,
200209
19 │ - }·from·"mod";
201-
20 14
202-
21 15import {/*a*/J/*b*/, /*c*/K/*d*/} from "mod";
210+
20 15
211+
21 16import {/*a*/J/*b*/, /*c*/K/*d*/} from "mod";
203212
204213
205214
```
@@ -220,12 +229,14 @@ invalid.js:21:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━
220229
221230
i Safe fix: Remove the unused imports.
222231
232+
17 17 │ H,
223233
18 18 │ I,
224-
19 19 │ } from "mod";
225-
20 │ -
234+
19 │ - }·from·"mod";
235+
19 │ + }·from·"mod";
236+
20 20 │
226237
21 │ - import·{/*a*/J/*b*//*c*/K/*d*/}·from·"mod";
227-
22 20
228-
23 21 │ // Header comment
238+
22 21
239+
23 22 │ // Header comment
229240
230241
231242
```
@@ -245,13 +256,15 @@ invalid.js:24:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━
245256
246257
i Safe fix: Remove the unused imports.
247258
259+
19 19 │ } from "mod";
248260
20 20 │
249-
21 21 │ import {/*a*/J/*b*/, /*c*/K/*d*/} from "mod";
250-
22 │ -
261+
21 │ - import·{/*a*/J/*b*//*c*/K/*d*/}·from·"mod";
262+
21 │ + import·{/*a*/J/*b*//*c*/K/*d*/}·from·"mod";
263+
22 22 │
251264
23 │ - //·Header·comment
252265
24 │ - import·{·L·as·M}·from·"mod";·//·Import·comment
253-
25 22
254-
26 23 │ // See https://github.com/biomejs/biome/issues/653
266+
25 23
267+
26 24 │ // See https://github.com/biomejs/biome/issues/653
255268
256269
257270
```
@@ -296,11 +309,13 @@ invalid.js:32:9 lint/correctness/noUnusedImports FIXABLE ━━━━━━━
296309
297310
i Safe fix: Remove the unused imports.
298311
312+
28 28 │ import {d} from 'd'
299313
29 29 │ import {b} from 'b'
300-
30 30 │ export const bb = a + b
301-
31 │ -
314+
30 │ - export·const·bb·=·a·+·b
315+
30 │ + export·const·bb·=·a·+·b
316+
31 31 │
302317
32 │ - import·{}·from·"mod"
303-
33 31
318+
33 32
304319
305320
306321
```

crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.jsx.snap

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,14 @@ invalid.jsx:5:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━━
110110
111111
i Safe fix: Remove the unused imports.
112112
113+
1 1 │ import X from "react"
113114
2 2 │ import * as X from "react"
114-
3 3 │ import { default as X } from "react"
115-
4 │ -
115+
3 │ - import·{·default·as·X·}·from·"react"
116+
3 │ + import·{·default·as·X·}·from·"react"
117+
4 4 │
116118
5 │ - import·React·from·"x"
117-
6 4 │ import * as React from "x"
118-
7 5 │ import { default as React } from "x"
119+
6 5 │ import * as React from "x"
120+
7 6 │ import { default as React } from "x"
119121
120122
121123
```
@@ -209,13 +211,15 @@ invalid.jsx:11:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━
209211
210212
i Safe fix: Remove the unused imports.
211213
214+
6 6 │ import * as React from "x"
212215
7 7 │ import { default as React } from "x"
213-
8 8 │ import React, { useEffect } from "x"
214-
9 │ -
216+
8 │ - import·React,·{·useEffect·}·from·"x"
217+
8 │ + import·React,·{·useEffect·}·from·"x"
218+
9 9 │
215219
10 │ - //·unsupported·patterns
216220
11 │ - import·X,·{·default·as·React·}·from·"react"
217-
12 9 │ import X, * as React from "react"
218-
13 10
221+
12 10 │ import X, * as React from "react"
222+
13 11
219223
220224
221225
```
@@ -260,13 +264,15 @@ invalid.jsx:15:8 lint/correctness/noUnusedImports FIXABLE ━━━━━━
260264
261265
i Safe fix: Remove the unused imports.
262266
267+
10 10 │ // unsupported patterns
263268
11 11 │ import X, { default as React } from "react"
264-
12 12 │ import X, * as React from "react"
265-
13 │ -
269+
12 │ - import·X,·*·as·React·from·"react"
270+
12 │ + import·X,·*·as·React·from·"react"
271+
13 13 │
266272
14 │ - //·React·import·(no·exception)
267273
15 │ - import·React·from·"react"
268-
16 13 │ import * as React from "react"
269-
17 14 │ import { default as React } from "react"
274+
16 14 │ import * as React from "react"
275+
17 15 │ import { default as React } from "react"
270276
271277
272278
```

crates/biome_js_analyze/tests/specs/correctness/noUnusedImports/invalid.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import type * as B from "mod"; // Import comment
77
// Header comment
88
import type { C } from "mod"; // Import comment
99

10+
// Orphan comment
11+
1012
// Header comment
1113
import /*a*/ D /*b*/, /*c*/{ type E }/*d*/ from "mod"; // Import comment
1214

@@ -22,3 +24,4 @@ import {/*a*/type J/*b*/, /*c*/type K/*d*/} from "mod";
2224

2325
// Header comment
2426
import type { L as M, } from "mod"; // Import comment
27+

0 commit comments

Comments
 (0)