Skip to content

Commit efd6be1

Browse files
richardxialjharb
authored andcommitted
[Fix] no-unused-modules: handle export { default } from syntax
Fixes #1631
1 parent adbced7 commit efd6be1

File tree

5 files changed

+63
-4
lines changed

5 files changed

+63
-4
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
99
- [`order`]: fix `isExternalModule` detect on windows ([#1651], thanks [@fisker])
1010
- [`order`]: recognize ".." as a "parent" path ([#1658], thanks [@golopot])
1111
- [`no-duplicates`]: fix fixer on cases with default import ([#1666], thanks [@golopot])
12+
- [`no-unused-modules`]: Handle `export { default } from` syntax ([#1631], thanks [@richardxia])
1213

1314
## [2.20.1] - 2020-02-01
1415
### Fixed
@@ -660,6 +661,7 @@ for info on changes for earlier releases.
660661
[#1658]: https://github.com/benmosher/eslint-plugin-import/pull/1658
661662
[#1651]: https://github.com/benmosher/eslint-plugin-import/pull/1651
662663
[#1635]: https://github.com/benmosher/eslint-plugin-import/issues/1635
664+
[#1631]: https://github.com/benmosher/eslint-plugin-import/issues/1631
663665
[#1625]: https://github.com/benmosher/eslint-plugin-import/pull/1625
664666
[#1620]: https://github.com/benmosher/eslint-plugin-import/pull/1620
665667
[#1619]: https://github.com/benmosher/eslint-plugin-import/pull/1619
@@ -1113,3 +1115,4 @@ for info on changes for earlier releases.
11131115
[@IvanGoncharov]: https://github.com/IvanGoncharov
11141116
[@wschurman]: https://github.com/wschurman
11151117
[@fisker]: https://github.com/fisker
1118+
[@richardxia]: https://github.com/richardxia

src/rules/no-unused-modules.js

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,54 @@ const CLASS_DECLARATION = 'ClassDeclaration'
6666
const DEFAULT = 'default'
6767
const TYPE_ALIAS = 'TypeAlias'
6868

69+
/**
70+
* List of imports per file.
71+
*
72+
* Represented by a two-level Map to a Set of identifiers. The upper-level Map
73+
* keys are the paths to the modules containing the imports, while the
74+
* lower-level Map keys are the paths to the files which are being imported
75+
* from. Lastly, the Set of identifiers contains either names being imported
76+
* or a special AST node name listed above (e.g ImportDefaultSpecifier).
77+
*
78+
* For example, if we have a file named foo.js containing:
79+
*
80+
* import { o2 } from './bar.js';
81+
*
82+
* Then we will have a structure that looks like:
83+
*
84+
* Map { 'foo.js' => Map { 'bar.js' => Set { 'o2' } } }
85+
*
86+
* @type {Map<string, Map<string, Set<string>>>}
87+
*/
6988
const importList = new Map()
89+
90+
/**
91+
* List of exports per file.
92+
*
93+
* Represented by a two-level Map to an object of metadata. The upper-level Map
94+
* keys are the paths to the modules containing the exports, while the
95+
* lower-level Map keys are the specific identifiers or special AST node names
96+
* being exported. The leaf-level metadata object at the moment only contains a
97+
* `whereUsed` propoerty, which contains a Set of paths to modules that import
98+
* the name.
99+
*
100+
* For example, if we have a file named bar.js containing the following exports:
101+
*
102+
* const o2 = 'bar';
103+
* export { o2 };
104+
*
105+
* And a file named foo.js containing the following import:
106+
*
107+
* import { o2 } from './bar.js';
108+
*
109+
* Then we will have a structure that looks like:
110+
*
111+
* Map { 'bar.js' => Map { 'o2' => { whereUsed: Set { 'foo.js' } } } }
112+
*
113+
* @type {Map<string, Map<string, object>>}
114+
*/
70115
const exportList = new Map()
116+
71117
const ignoredFiles = new Set()
72118
const filesOutsideSrc = new Set()
73119

@@ -453,9 +499,12 @@ module.exports = {
453499
}
454500
}
455501

456-
const exportStatement = exports.get(exportedValue)
502+
// exportsList will always map any imported value of 'default' to 'ImportDefaultSpecifier'
503+
const exportsKey = exportedValue === DEFAULT ? IMPORT_DEFAULT_SPECIFIER : exportedValue
504+
505+
const exportStatement = exports.get(exportsKey)
457506

458-
const value = exportedValue === IMPORT_DEFAULT_SPECIFIER ? DEFAULT : exportedValue
507+
const value = exportsKey === IMPORT_DEFAULT_SPECIFIER ? DEFAULT : exportsKey
459508

460509
if (typeof exportStatement !== 'undefined'){
461510
if (exportStatement.whereUsed.size < 1) {

tests/files/no-unused-modules/file-0.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ import {q} from './file-q'
1111
export * from './file-n'
1212
export { default, o0, o3 } from './file-o'
1313
export { p } from './file-p'
14+
import s from './file-s'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from './file-o'

tests/src/rules/no-unused-modules.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ ruleTester.run('no-unused-modules', rule, {
110110
import * as l from './file-l'
111111
export * from './file-n'
112112
export { default, o0, o3 } from './file-o'
113-
export { p } from './file-p'`,
113+
export { p } from './file-p'
114+
import s from './file-s'`,
114115
filename: testFilePath('./no-unused-modules/file-0.js'),
115116
errors: [
116117
error(`exported declaration 'default' not used within other modules`),
@@ -165,7 +166,11 @@ ruleTester.run('no-unused-modules', rule, {
165166

166167
// // test for export from
167168
ruleTester.run('no-unused-modules', rule, {
168-
valid: [],
169+
valid: [
170+
test({ options: unusedExportsOptions,
171+
code: `export { default } from './file-o'`,
172+
filename: testFilePath('./no-unused-modules/file-s.js')}),
173+
],
169174
invalid: [
170175
test({ options: unusedExportsOptions,
171176
code: `export { k } from '${testFilePath('./no-unused-modules/file-k.js')}'`,

0 commit comments

Comments
 (0)