Skip to content

Commit 35d5cb5

Browse files
committed
Merge pull request #351 from benmosher/fix-prefer-default
Fix prefer default (#342, #343, #350, #351) #MostPRsEver
2 parents c15901b + 445e1e1 commit 35d5cb5

5 files changed

Lines changed: 90 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
1414
- Make [`order`]'s `newline-between` option handle multiline import statements ([#313], thanks [@singles])
1515
- Make [`order`]'s `newline-between` option handle not assigned import statements ([#313], thanks [@singles])
1616
- Make [`order`]'s `newline-between` option ignore `require` statements inside object literals ([#313], thanks [@singles])
17+
- [`prefer-default-export`] properly handles deep destructuring, `export * from ...`, and files with no exports. ([#342]+[#343], thanks [@scottnonnenberg])
1718

1819
## [1.8.0] - 2016-05-11
1920
### Added
@@ -224,6 +225,7 @@ for info on changes for earlier releases.
224225
[`no-mutable-exports`]: ./docs/rules/no-mutable-exports.md
225226
[`prefer-default-export`]: ./docs/rules/prefer-default-export.md
226227

228+
[#343]: https://github.com/benmosher/eslint-plugin-import/pull/343
227229
[#332]: https://github.com/benmosher/eslint-plugin-import/pull/332
228230
[#322]: https://github.com/benmosher/eslint-plugin-import/pull/322
229231
[#316]: https://github.com/benmosher/eslint-plugin-import/pull/316
@@ -250,6 +252,7 @@ for info on changes for earlier releases.
250252
[#164]: https://github.com/benmosher/eslint-plugin-import/pull/164
251253
[#157]: https://github.com/benmosher/eslint-plugin-import/pull/157
252254

255+
[#342]: https://github.com/benmosher/eslint-plugin-import/issues/342
253256
[#328]: https://github.com/benmosher/eslint-plugin-import/issues/328
254257
[#317]: https://github.com/benmosher/eslint-plugin-import/issues/317
255258
[#286]: https://github.com/benmosher/eslint-plugin-import/issues/286
@@ -307,3 +310,4 @@ for info on changes for earlier releases.
307310
[@borisyankov]: https://github.com/borisyankov
308311
[@gavriguy]: https://github.com/gavriguy
309312
[@jkimbo]: https://github.com/jkimbo
313+
[@scottnonnenberg]: https://github.com/scottnonnenberg

docs/rules/prefer-default-export.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,10 @@ export { foo, bar }
4949
const foo = 'foo';
5050
export { foo as default }
5151
```
52+
53+
```javascript
54+
// export-star.js
55+
56+
// Any batch export will disable this rule. The remote module is not inspected.
57+
export * from './other-module'
58+
```

src/rules/newline-after-import.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ module.exports = function (context) {
9696
return
9797
}
9898

99-
if (nextStatement && (!nextRequireCall || !containsNodeOrEqual(nextStatement, nextRequireCall))) {
99+
if (nextStatement &&
100+
(!nextRequireCall || !containsNodeOrEqual(nextStatement, nextRequireCall))) {
101+
100102
checkForNewLine(statementWithRequireCall, nextStatement, 'require')
101103
}
102104
})

src/rules/prefer-default-export.js

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
'use strict'
22

33
module.exports = function(context) {
4-
let namedExportCount = 0
54
let specifierExportCount = 0
65
let hasDefaultExport = false
6+
let hasStarExport = false
77
let namedExportNode = null
8+
89
return {
910
'ExportSpecifier': function(node) {
1011
if (node.exported.name === 'default') {
@@ -14,16 +15,43 @@ module.exports = function(context) {
1415
namedExportNode = node
1516
}
1617
},
18+
1719
'ExportNamedDeclaration': function(node) {
18-
namedExportCount++
20+
// if there are specifiers, node.declaration should be null
21+
if (!node.declaration) return
22+
23+
function captureDeclaration(identifierOrPattern) {
24+
if (identifierOrPattern.type === 'ObjectPattern') {
25+
// recursively capture
26+
identifierOrPattern.properties
27+
.forEach(function(property) {
28+
captureDeclaration(property.value)
29+
})
30+
} else {
31+
// assume it's a single standard identifier
32+
specifierExportCount++
33+
}
34+
}
35+
36+
if (node.declaration.declarations) {
37+
node.declaration.declarations.forEach(function(declaration) {
38+
captureDeclaration(declaration.id)
39+
})
40+
}
41+
1942
namedExportNode = node
2043
},
44+
2145
'ExportDefaultDeclaration': function() {
2246
hasDefaultExport = true
2347
},
2448

49+
'ExportAllDeclaration': function() {
50+
hasStarExport = true
51+
},
52+
2553
'Program:exit': function() {
26-
if (namedExportCount === 1 && specifierExportCount < 2 && !hasDefaultExport) {
54+
if (specifierExportCount === 1 && !hasDefaultExport && !hasStarExport) {
2755
context.report(namedExportNode, 'Prefer default export.')
2856
}
2957
},

tests/src/rules/prefer-default-export.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,39 @@ ruleTester.run('prefer-default-export', rule, {
2121
code: `
2222
export { foo, bar }`,
2323
}),
24+
test({
25+
code: `
26+
export const { foo, bar } = item;`,
27+
}),
28+
test({
29+
code: `
30+
export const { foo, bar: baz } = item;`,
31+
}),
32+
test({
33+
code: `
34+
export const { foo: { bar, baz } } = item;`,
35+
}),
36+
test({
37+
code: `
38+
export const foo = item;
39+
export { item };`,
40+
}),
2441
test({
2542
code: `
2643
export { foo as default }`,
2744
}),
45+
test({
46+
code: `
47+
export * from './foo';`,
48+
}),
49+
50+
// no exports at all
51+
test({
52+
code: `
53+
import * as foo from './foo';`,
54+
}),
55+
56+
// ...SYNTAX_CASES,
2857
],
2958
invalid: [
3059
test({
@@ -44,5 +73,21 @@ ruleTester.run('prefer-default-export', rule, {
4473
message: 'Prefer default export.',
4574
}],
4675
}),
76+
test({
77+
code: `
78+
export const { foo } = { foo: "bar" };`,
79+
errors: [{
80+
ruleId: 'ExportNamedDeclaration',
81+
message: 'Prefer default export.',
82+
}],
83+
}),
84+
test({
85+
code: `
86+
export const { foo: { bar } } = { foo: { bar: "baz" } };`,
87+
errors: [{
88+
ruleId: 'ExportNamedDeclaration',
89+
message: 'Prefer default export.',
90+
}],
91+
}),
4792
],
4893
})

0 commit comments

Comments
 (0)