Skip to content

Commit

Permalink
fix(lint): Handle non-import declaration nodes in import-sort rule
Browse files Browse the repository at this point in the history
Non-import declaration nodes found between the first and last import statements are currently just removed leading to
unexpected behavior. In this commit, such nodes are collected and written back to the end of the import declarations.
  • Loading branch information
vigneshm authored and mergify[bot] committed Feb 17, 2021
1 parent 803892a commit b34f8ca
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 3 deletions.
33 changes: 32 additions & 1 deletion packages/eslint-plugin/rules/import-sort.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,24 @@ const getText = (importDeclarations) => {
}, '');
};

/**
* Returns all non `ImportDeclaration` nodes that appear between the first and last `ImportDeclaration` nodes.
*/
const getAllNonImportDeclarationNodes = (body) => {
const importDeclarations = body.filter((node) => node.type === 'ImportDeclaration');
const startIndex = body.findIndex((node) => node.type === 'ImportDeclaration');
const lastIndex = body.findIndex((node) => node == importDeclarations[importDeclarations.length - 1]);

const nonImportDeclarationNodes = [];
for (let i = startIndex; i <= lastIndex; i++) {
if (body[i].type !== 'ImportDeclaration') {
nonImportDeclarationNodes.push(body[i]);
}
}

return nonImportDeclarationNodes;
};

/**
* @type {RuleModule}
*
Expand All @@ -169,6 +187,9 @@ module.exports = {
if (!importDeclarations.length) {
return;
}
// Nodes between first and last `ImportDeclarationNodes` that aren't of type `ImportDeclaration`. These nodes
// must be re-written at the end of the import declarations.
const nonImportDeclarationNodes = getAllNonImportDeclarationNodes(program.body);
const start = importDeclarations[0].range[0];
const end = importDeclarations[importDeclarations.length - 1].range[1];
const originalTextOfImportDeclarations = getText(importDeclarations);
Expand Down Expand Up @@ -221,8 +242,18 @@ module.exports = {
// Combine sorted declarations from each partition
.join('\n\n');

const sourceCode = context.getSourceCode();
const nonImportDeclarationsText =
nonImportDeclarationNodes.length > 0
? nonImportDeclarationNodes.map((node) => sourceCode.getText(node)).join('\n')
: null;

const fixedText = nonImportDeclarationsText
? `${importDeclarationsText}\n\n${nonImportDeclarationsText}`
: importDeclarationsText;

context.report({
fix: (fixer) => fixer.replaceTextRange([start, end], importDeclarationsText),
fix: (fixer) => fixer.replaceTextRange([start, end], fixedText),
message: 'Sort the import statements',
node: importDeclarations[0],
});
Expand Down
8 changes: 6 additions & 2 deletions packages/eslint-plugin/test/import-sort.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ import * as Select from 'react-select';
},
{
code: `
import React, {useState, useCallback} from 'react';
import React from 'react';
const {useState, useCallback} = React;
import Bar from "./bar";
import angular from 'angular';
Expand All @@ -63,7 +65,7 @@ import 'bootstrap.less';
output: `
import angular from 'angular';
import 'jquery';
import React, { useCallback, useState } from 'react';
import React from 'react';
// Some comment about react-select
import * as Select from 'react-select';
Expand All @@ -74,6 +76,8 @@ import Baz from '../../../test/baz';
import 'bootstrap.less';
import './styles.less';
const {useState, useCallback} = React;
`,
errors: ['Sort the import statements'],
},
Expand Down

0 comments on commit b34f8ca

Please sign in to comment.