Skip to content

Commit

Permalink
Update: Allows for grouped sort-imports (fixes eslint#12951)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dimitar committed Feb 23, 2020
1 parent aa9d725 commit 96b1881
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 3 deletions.
53 changes: 53 additions & 0 deletions docs/rules/sort-imports.md
Expand Up @@ -36,6 +36,7 @@ This rule accepts an object with its properties as
* `ignoreCase` (default: `false`)
* `ignoreDeclarationSort` (default: `false`)
* `ignoreMemberSort` (default: `false`)
* `ignoreBlankLines` (default: `true`)
* `memberSyntaxSortOrder` (default: `["none", "all", "multiple", "single"]`); all 4 items must be present in the array, but you can change the order:
* `none` = import module without exported bindings.
* `all` = import all members provided by exported bindings.
Expand All @@ -50,6 +51,7 @@ Default option settings are:
"ignoreCase": false,
"ignoreDeclarationSort": false,
"ignoreMemberSort": false,
"ignoreBlankLines": true,
"memberSyntaxSortOrder": ["none", "all", "multiple", "single"]
}]
}
Expand Down Expand Up @@ -84,6 +86,13 @@ import c from 'qux.js';

/*eslint sort-imports: "error"*/
import {a, b, c} from 'foo.js'

/*eslint sort-imports: "error"*/
import a from 'bar.js';

import b from 'foo.js';

import c from 'baz.js';
```

Examples of **incorrect** code for this rule when using default options:
Expand All @@ -93,6 +102,11 @@ Examples of **incorrect** code for this rule when using default options:
import b from 'foo.js';
import a from 'bar.js';

/*eslint sort-imports: "error"*/
import b from 'foo.js';

import a from 'bar.js';

/*eslint sort-imports: "error"*/
import a from 'foo.js';
import A from 'bar.js';
Expand Down Expand Up @@ -186,6 +200,45 @@ import {b, a, c} from 'foo.js'

Default is `false`.

### `ignoreBlankLines`

When `true` the rule ignores the blank lines between the imports.

Examples of **incorrect** code for this rule with the default `{ "ignoreBlankLines": true }` option:

```js
/*eslint sort-imports: ["error", { "ignoreBlankLines": true }]*/
import b from 'foo.js'

import a from 'bar.js'


/*eslint sort-imports: ["error", { "ignoreBlankLines": true }]*/
import b from 'foo.js';
import c from 'baz.js';

import a from 'bar.js';
import x from 'qux.js';
```

Examples of **correct** code for this rule with the `{ "ignoreBlankLines": false }` option:

```js
/*eslint sort-imports: ["error", { "ignoreDeclarationSort": true }]*/
import b from 'bar.js'

import a from 'foo.js'

/*eslint sort-imports: ["error", { "ignoreBlankLines": false }]*/
import b from 'foo.js';
import c from 'baz.js';

import a from 'bar.js';
import x from 'qux.js';
```

Default is `true`.

### `memberSyntaxSortOrder`

There are four different styles and the default member syntax sort order is:
Expand Down
20 changes: 18 additions & 2 deletions lib/rules/sort-imports.js
Expand Up @@ -44,6 +44,10 @@ module.exports = {
ignoreMemberSort: {
type: "boolean",
default: false
},
ignoreBlankLines: {
type: "boolean",
default: true
}
},
additionalProperties: false
Expand All @@ -65,6 +69,7 @@ module.exports = {
ignoreCase = configuration.ignoreCase || false,
ignoreDeclarationSort = configuration.ignoreDeclarationSort || false,
ignoreMemberSort = configuration.ignoreMemberSort || false,
ignoreBlankLines = configuration.ignoreBlankLines !== false,
memberSyntaxSortOrder = configuration.memberSyntaxSortOrder || ["none", "all", "multiple", "single"],
sourceCode = context.getSourceCode();
let previousDeclaration = null;
Expand Down Expand Up @@ -112,15 +117,25 @@ module.exports = {
return node.specifiers[0].local.name;
}
return null;
}

/**
* Gets the number of lines between the given declarations.
* @param {ASTNode} node1 the ImportDeclaration node.
* @param {ASTNode} node2 the ImportDeclaration node.
* @returns {number} number of lines.
*/
function getLinesBetweenMembers(node1, node2) {
return node1.loc.start.line - node2.loc.end.line - 1;
}

return {
ImportDeclaration(node) {
if (!ignoreDeclarationSort) {
if (previousDeclaration) {
const currentMemberSyntaxGroupIndex = getMemberParameterGroupIndex(node),
previousMemberSyntaxGroupIndex = getMemberParameterGroupIndex(previousDeclaration);
previousMemberSyntaxGroupIndex = getMemberParameterGroupIndex(previousDeclaration),
linesBetweenMembers = getLinesBetweenMembers(node, previousDeclaration);
let currentLocalMemberName = getFirstLocalMemberName(node),
previousLocalMemberName = getFirstLocalMemberName(previousDeclaration);

Expand Down Expand Up @@ -148,7 +163,8 @@ module.exports = {
} else {
if (previousLocalMemberName &&
currentLocalMemberName &&
currentLocalMemberName < previousLocalMemberName
currentLocalMemberName < previousLocalMemberName &&
(ignoreBlankLines || linesBetweenMembers < 1)
) {
context.report({
node,
Expand Down
21 changes: 20 additions & 1 deletion tests/lib/rules/sort-imports.js
Expand Up @@ -101,7 +101,17 @@ ruleTester.run("sort-imports", rule, {
},

// https://github.com/eslint/eslint/issues/5305
"import React, {Component} from 'react';"
"import React, {Component} from 'react';",

// https://github.com/eslint/eslint/issues/12951
{
code:
"import b from 'foo.js';\n\n" +
"import a from 'bar.js';",
options: [{
ignoreBlankLines: false
}]
}
],
invalid: [
{
Expand Down Expand Up @@ -287,6 +297,15 @@ ruleTester.run("sort-imports", rule, {
data: { memberName: "qux" },
type: "ImportSpecifier"
}]
},

// https://github.com/eslint/eslint/issues/12951
{
code:
"import b from 'foo.js';\n\n" +
"import a from 'bar.js';",
output: null,
errors: [expectedError]
}
]
});

0 comments on commit 96b1881

Please sign in to comment.