Skip to content

Commit 449738f

Browse files
fix(no-duplicates): autofix insert type prefix without new line (#206)
1 parent af711e5 commit 449738f

File tree

3 files changed

+55
-16
lines changed

3 files changed

+55
-16
lines changed

.changeset/tame-melons-notice.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"eslint-plugin-import-x": patch
3+
---
4+
5+
insert type prefix without new line

src/rules/no-duplicates.ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -172,13 +172,15 @@ function getFix(
172172
specifier.identifiers.reduce(
173173
([text, set], cur) => {
174174
const trimmed = cur.trim() // Trim whitespace before/after to compare to our set of existing identifiers
175-
const curWithType =
176-
trimmed.length > 0 && preferInline && isTypeSpecifier
177-
? `type ${cur}`
178-
: cur
179-
if (existingIdentifiers.has(trimmed)) {
175+
if (trimmed.length === 0 || existingIdentifiers.has(trimmed)) {
180176
return [text, set]
181177
}
178+
179+
const curWithType =
180+
preferInline && isTypeSpecifier
181+
? cur.replace(/^(\s*)/, '$1type ')
182+
: cur
183+
182184
return [
183185
text.length > 0 ? `${text},${curWithType}` : curWithType,
184186
set.add(trimmed),
@@ -267,8 +269,9 @@ function getFix(
267269
)
268270
}
269271
} else if (openBrace != null && closeBrace != null && !shouldAddDefault()) {
272+
const tokenBefore = sourceCode.getTokenBefore(closeBrace)!
270273
// `import {...} './foo'` → `import {..., ...} from './foo'`
271-
fixes.push(fixer.insertTextBefore(closeBrace, specifiersText))
274+
fixes.push(fixer.insertTextAfter(tokenBefore, specifiersText))
272275
}
273276

274277
// Remove imports whose specifiers have been moved into the first import.

test/rules/no-duplicates.spec.ts

+41-10
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ ruleTester.run('no-duplicates', rule, {
7070
invalid: [
7171
tInvalid({
7272
code: "import { x } from './foo'; import { y } from './foo'",
73-
output: "import { x , y } from './foo'; ",
73+
output: "import { x, y } from './foo'; ",
7474
errors: [createDuplicatedError('./foo'), createDuplicatedError('./foo')],
7575
}),
7676

@@ -87,7 +87,7 @@ ruleTester.run('no-duplicates', rule, {
8787
// ensure resolved path results in warnings
8888
tInvalid({
8989
code: "import { x } from './bar'; import { y } from 'bar';",
90-
output: "import { x , y } from './bar'; ",
90+
output: "import { x, y } from './bar'; ",
9191
settings: {
9292
'import-x/resolve': {
9393
paths: [path.resolve('test/fixtures')],
@@ -133,7 +133,7 @@ ruleTester.run('no-duplicates', rule, {
133133

134134
tInvalid({
135135
code: "import type { x } from './foo'; import type { y } from './foo'",
136-
output: "import type { x , y } from './foo'; ",
136+
output: "import type { x, y } from './foo'; ",
137137
languageOptions: { parser: require(parsers.BABEL) },
138138
errors: [createDuplicatedError('./foo'), createDuplicatedError('./foo')],
139139
}),
@@ -146,7 +146,7 @@ ruleTester.run('no-duplicates', rule, {
146146

147147
tInvalid({
148148
code: "import { x, /* x */ } from './foo'; import {//y\ny//y2\n} from './foo'",
149-
output: "import { x, /* x */ //y\ny//y2\n} from './foo'; ",
149+
output: "import { x,//y\ny//y2\n /* x */ } from './foo'; ",
150150
languageOptions: { parser: require(parsers.ESPREE) },
151151
errors: [createDuplicatedError('./foo'), createDuplicatedError('./foo')],
152152
}),
@@ -195,7 +195,7 @@ ruleTester.run('no-duplicates', rule, {
195195

196196
tInvalid({
197197
code: "import { } from './foo'; import {x} from './foo'",
198-
output: "import { x} from './foo'; ",
198+
output: "import {x } from './foo'; ",
199199
errors: [createDuplicatedError('./foo'), createDuplicatedError('./foo')],
200200
}),
201201

@@ -419,7 +419,7 @@ import {x,y} from './foo'
419419
// #2027 long import list generate empty lines
420420
tInvalid({
421421
code: "import { Foo } from './foo';\nimport { Bar } from './foo';\nexport const value = {}",
422-
output: "import { Foo , Bar } from './foo';\nexport const value = {}",
422+
output: "import { Foo, Bar } from './foo';\nexport const value = {}",
423423
errors: [createDuplicatedError('./foo'), createDuplicatedError('./foo')],
424424
}),
425425

@@ -452,8 +452,8 @@ export default TestComponent;
452452
import {
453453
DEFAULT_FILTER_KEYS,
454454
BULK_DISABLED,
455-
456455
BULK_ACTIONS_ENABLED
456+
457457
} from '../constants';
458458
import React from 'react';
459459
@@ -493,9 +493,9 @@ export default TestComponent;
493493
${''}
494494
import {
495495
A2,
496-
${''}
497496
B2,
498-
C2} from 'bar';
497+
C2
498+
} from 'bar';
499499
${''}
500500
`,
501501
errors: [
@@ -822,7 +822,7 @@ describe('TypeScript', () => {
822822
code: "import type { AType as BType } from './foo'; import { CValue } from './foo'",
823823
...parserConfig,
824824
options: [{ 'prefer-inline': true }],
825-
output: `import { type AType as BType , CValue } from './foo'; `,
825+
output: `import { type AType as BType, CValue } from './foo'; `,
826826
errors: [
827827
{
828828
...createDuplicatedError('./foo'),
@@ -836,6 +836,37 @@ describe('TypeScript', () => {
836836
},
837837
],
838838
}),
839+
tInvalid({
840+
code: `
841+
import {
842+
a
843+
} from './foo';
844+
import type {
845+
b,
846+
c,
847+
} from './foo';`,
848+
...parserConfig,
849+
options: [{ 'prefer-inline': true }],
850+
output: `
851+
import {
852+
a,
853+
type b,
854+
type c
855+
} from './foo';
856+
`,
857+
errors: [
858+
{
859+
...createDuplicatedError('./foo'),
860+
line: 4,
861+
column: 20,
862+
},
863+
{
864+
...createDuplicatedError('./foo'),
865+
line: 8,
866+
column: 20,
867+
},
868+
],
869+
}),
839870
]),
840871
]
841872

0 commit comments

Comments
 (0)