Skip to content

fix(extensions): always calculate fix option #393

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/angry-lions-learn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eslint-plugin-import-x": patch
---

fix(extensions): always calculate `fix` option
12 changes: 12 additions & 0 deletions docs/rules/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@

<!-- end auto-generated rule header -->

> [!NOTE]
>
> This rule is only fixable when the `fix` option is set to `true` for compatibility, otherwise `suggestions` will be provided instead.
>
> Example:
>
> ```json
> "import-x/extensions": ["error", "never", { "fix": true }]
> ```
>
> It will change to be automatically fixable in the next major version.

Some file resolve algorithms allow you to omit the file extension within the import source path. For example the `node` resolver (which does not yet support ESM/`import`) can resolve `./foo/bar` to the absolute path `/User/someone/foo/bar.js` because the `.js` extension is resolved automatically by default in CJS. Depending on the resolver you can configure more extensions to get resolved automatically.

In order to provide a consistent use of file extensions across your code base, this rule can enforce or disallow the use of certain file extensions.
Expand Down
8 changes: 4 additions & 4 deletions src/rules/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ function buildProperties(context: RuleContext<MessageId, Options>) {
continue
}

if (obj.fix != null) {
result.fix = Boolean(obj.fix)
}

// If this is not the new structure, transfer all props to result.pattern
if (
(!('pattern' in obj) || obj.pattern == null) &&
Expand All @@ -156,10 +160,6 @@ function buildProperties(context: RuleContext<MessageId, Options>) {
result.checkTypeImports = obj.checkTypeImports
}

if (obj.fix != null) {
result.fix = Boolean(obj.fix)
}

if (Array.isArray(obj.pathGroupOverrides)) {
result.pathGroupOverrides = obj.pathGroupOverrides
}
Expand Down
77 changes: 77 additions & 0 deletions test/rules/extensions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,83 @@ ruleTester.run('extensions', rule, {
],

invalid: [
tInvalid({
name: 'extensions should provide suggestions by default',
code: 'import a from "./foo.js"',
options: ['never'],
errors: [
{
messageId: 'unexpected',
data: { extension: 'js', importPath: './foo.js' },
line: 1,
column: 15,
suggestions: [
{
messageId: 'removeUnexpected',
data: {
extension: 'js',
importPath: './foo.js',
fixedImportPath: './foo',
},
output: 'import a from "./foo"',
},
],
},
],
}),
tInvalid({
name: 'extensions should autofix when fix is set to true',
code: 'import a from "./foo.js"',
options: ['never', { fix: true }],
errors: [
{
messageId: 'unexpected',
data: { extension: 'js', importPath: './foo.js' },
line: 1,
column: 15,
},
],
output: 'import a from "./foo"',
}),
tInvalid({
name: 'extensions should autofix when fix is set to true and a pattern object is provided',
code: 'import a from "./foo.js"',
options: ['never', { fix: true, pattern: {} }],
errors: [
{
messageId: 'unexpected',
data: { extension: 'js', importPath: './foo.js' },
line: 1,
column: 15,
},
],
output: 'import a from "./foo"',
}),
tInvalid({
name: 'extensions should not autofix when fix is set to false',
code: 'import a from "./foo.js"',
options: ['never', { fix: false }],
errors: [
{
messageId: 'unexpected',
data: { extension: 'js', importPath: './foo.js' },
line: 1,
column: 15,
suggestions: [
{
messageId: 'removeUnexpected',
data: {
extension: 'js',
importPath: './foo.js',
fixedImportPath: './foo',
},
output: 'import a from "./foo"',
},
],
},
],
output: null,
}),
tInvalid({
code: 'import a from "a/index.js"',
errors: [
Expand Down