diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c6740ef48..fad28d7da7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel - [`newline-after-import`]: respect decorator annotations ([#1985], thanks [@lilling]) - [`no-restricted-paths`]: enhance performance for zones with `except` paths ([#2022], thanks [@malykhinvi]) - [`no-unresolved`]: check import() ([#2026], thanks [@aladdin-add]) +- [`no-duplicates`]: ensure autofix avoids excessive newlines ([#2028], thanks [@ertrzyiks]) ### Changed - [Generic Import Callback] Make callback for all imports once in rules ([#1237], thanks [@ljqx]) @@ -770,6 +771,7 @@ for info on changes for earlier releases. [`memo-parser`]: ./memo-parser/README.md [#2034]: https://github.com/benmosher/eslint-plugin-import/pull/2034 +[#2028]: https://github.com/benmosher/eslint-plugin-import/pull/2028 [#2026]: https://github.com/benmosher/eslint-plugin-import/pull/2026 [#2022]: https://github.com/benmosher/eslint-plugin-import/pull/2022 [#2021]: https://github.com/benmosher/eslint-plugin-import/pull/2021 @@ -1368,4 +1370,5 @@ for info on changes for earlier releases. [@aladdin-add]: https://github.com/aladdin-add [@davidbonnet]: https://github.com/davidbonnet [@hayes]: https://github.com/hayes -[@edemaine]: https://github.com/edemaine \ No newline at end of file +[@edemaine]: https://github.com/edemaine +[@ertrzyiks]: https://github.com/ertrzyiks diff --git a/src/rules/no-duplicates.js b/src/rules/no-duplicates.js index 1bf6f38245..4df4a88600 100644 --- a/src/rules/no-duplicates.js +++ b/src/rules/no-duplicates.js @@ -150,7 +150,14 @@ function getFix(first, rest, sourceCode) { // Remove imports whose specifiers have been moved into the first import. for (const specifier of specifiers) { - fixes.push(fixer.remove(specifier.importNode)); + const importNode = specifier.importNode; + fixes.push(fixer.remove(importNode)); + + const charAfterImportRange = [importNode.range[1], importNode.range[1] + 1] + const charAfterImport = sourceCode.text.substring(charAfterImportRange[0], charAfterImportRange[1]); + if (charAfterImport === '\n') { + fixes.push(fixer.removeRange(charAfterImportRange)); + } } // Remove imports whose default import has been moved to the first import, @@ -158,6 +165,12 @@ function getFix(first, rest, sourceCode) { // import. for (const node of unnecessaryImports) { fixes.push(fixer.remove(node)); + + const charAfterImportRange = [node.range[1], node.range[1] + 1]; + const charAfterImport = sourceCode.text.substring(charAfterImportRange[0], charAfterImportRange[1]); + if (charAfterImport === '\n') { + fixes.push(fixer.removeRange(charAfterImportRange)); + } } return fixes; diff --git a/tests/src/rules/no-duplicates.js b/tests/src/rules/no-duplicates.js index 6b5bc739d5..322da1028f 100644 --- a/tests/src/rules/no-duplicates.js +++ b/tests/src/rules/no-duplicates.js @@ -400,6 +400,21 @@ ruleTester.run('no-duplicates', rule, { `, errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'], }), + + + // #2027 long import list generate empty lines + test({ + code: "import { Foo } from './foo';\nimport { Bar } from './foo';\nexport const value = {}", + output: "import { Foo , Bar } from './foo';\nexport const value = {}", + errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'], + }), + + // #2027 long import list generate empty lines + test({ + code: "import { Foo } from './foo';\nimport Bar from './foo';\nexport const value = {}", + output: "import Bar, { Foo } from './foo';\nexport const value = {}", + errors: ['\'./foo\' imported multiple times.', '\'./foo\' imported multiple times.'], + }), ], }); @@ -430,4 +445,3 @@ context('TypeScript', function() { }); }); }); -