From ab0181d79c6959e6c5cfe25343d8648c1b275bf6 Mon Sep 17 00:00:00 2001 From: Andreas Opferkuch Date: Sun, 28 Feb 2021 16:27:27 +0100 Subject: [PATCH] [New] `no-unused-modules`: Support destructuring --- CHANGELOG.md | 3 +++ src/rules/no-unused-modules.js | 14 +++++++++++-- .../no-unused-modules/destructuring-a.js | 1 + .../no-unused-modules/destructuring-b.js | 2 ++ tests/src/rules/no-unused-modules.js | 20 +++++++++++++++++++ 5 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 tests/files/no-unused-modules/destructuring-a.js create mode 100644 tests/files/no-unused-modules/destructuring-b.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b9edced6..edcde8533 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel - [`no-internal-modules`]: Add `forbid` option ([#1846], thanks [@guillaumewuip]) - add [`no-relative-packages`] ([#1860], [#966], thanks [@tapayne88] [@panrafal]) - add [`no-import-module-exports`] rule: report import declarations with CommonJS exports ([#804], thanks [@kentcdodds] and [@ttmarek]) +- [`no-unused-modules`]: Support destructuring assignment for `export`. ([#1997], thanks [@s-h-a-d-o-w]) ### Fixed - [`export`]/TypeScript: properly detect export specifiers as children of a TS module block ([#1889], thanks [@andreubotella]) @@ -760,6 +761,7 @@ for info on changes for earlier releases. [`memo-parser`]: ./memo-parser/README.md +[#1997]: https://github.com/benmosher/eslint-plugin-import/pull/1997 [#1993]: https://github.com/benmosher/eslint-plugin-import/pull/1993 [#1983]: https://github.com/benmosher/eslint-plugin-import/pull/1983 [#1974]: https://github.com/benmosher/eslint-plugin-import/pull/1974 @@ -1344,3 +1346,4 @@ for info on changes for earlier releases. [@christianvuerings]: https://github.com/christianvuerings [@devongovett]: https://github.com/devongovett [@dwardu]: https://github.com/dwardu +[@s-h-a-d-o-w]: https://github.com/s-h-a-d-o-w diff --git a/src/rules/no-unused-modules.js b/src/rules/no-unused-modules.js index dfea6de6d..99b564eda 100644 --- a/src/rules/no-unused-modules.js +++ b/src/rules/no-unused-modules.js @@ -4,7 +4,7 @@ * @author René Fermann */ -import Exports from '../ExportMap'; +import Exports, { recursivePatternCapture } from '../ExportMap'; import { getFileExtensions } from 'eslint-module-utils/ignore'; import resolve from 'eslint-module-utils/resolve'; import docsUrl from '../docsUrl'; @@ -63,6 +63,8 @@ const IMPORT_DEFAULT_SPECIFIER = 'ImportDefaultSpecifier'; const VARIABLE_DECLARATION = 'VariableDeclaration'; const FUNCTION_DECLARATION = 'FunctionDeclaration'; const CLASS_DECLARATION = 'ClassDeclaration'; +const IDENTIFIER = 'Identifier'; +const OBJECT_PATTERN = 'ObjectPattern'; const TS_INTERFACE_DECLARATION = 'TSInterfaceDeclaration'; const TS_TYPE_ALIAS_DECLARATION = 'TSTypeAliasDeclaration'; const TS_ENUM_DECLARATION = 'TSEnumDeclaration'; @@ -80,7 +82,15 @@ function forEachDeclarationIdentifier(declaration, cb) { cb(declaration.id.name); } else if (declaration.type === VARIABLE_DECLARATION) { declaration.declarations.forEach(({ id }) => { - cb(id.name); + if (id.type === OBJECT_PATTERN) { + recursivePatternCapture(id, (pattern) => { + if (pattern.type === IDENTIFIER) { + cb(pattern.name); + } + }); + } else { + cb(id.name); + } }); } } diff --git a/tests/files/no-unused-modules/destructuring-a.js b/tests/files/no-unused-modules/destructuring-a.js new file mode 100644 index 000000000..1da867def --- /dev/null +++ b/tests/files/no-unused-modules/destructuring-a.js @@ -0,0 +1 @@ +import {a, b} from "./destructuring-b"; diff --git a/tests/files/no-unused-modules/destructuring-b.js b/tests/files/no-unused-modules/destructuring-b.js new file mode 100644 index 000000000..b477a5b6f --- /dev/null +++ b/tests/files/no-unused-modules/destructuring-b.js @@ -0,0 +1,2 @@ +const obj = {a: 1, dummy: {b: 2}}; +export const {a, dummy: {b}} = obj; diff --git a/tests/src/rules/no-unused-modules.js b/tests/src/rules/no-unused-modules.js index e1f1ddb6c..cd054ecb9 100644 --- a/tests/src/rules/no-unused-modules.js +++ b/tests/src/rules/no-unused-modules.js @@ -970,3 +970,23 @@ describe('ignore flow types', () => { invalid: [], }); }); + +describe('support (nested) destructuring assignment', () => { + ruleTester.run('no-unused-modules', rule, { + valid: [ + test({ + options: unusedExportsOptions, + code: 'import {a, b} from "./destructuring-b";', + parser: require.resolve('babel-eslint'), + filename: testFilePath('./no-unused-modules/destructuring-a.js'), + }), + test({ + options: unusedExportsOptions, + code: 'const obj = {a: 1, dummy: {b: 2}}; export const {a, dummy: {b}} = obj;', + parser: require.resolve('babel-eslint'), + filename: testFilePath('./no-unused-modules/destructuring-b.js'), + }), + ], + invalid: [], + }); +});