Skip to content

Commit

Permalink
Refactor exports-last
Browse files Browse the repository at this point in the history
  • Loading branch information
k15a committed Jan 25, 2017
1 parent d9028c5 commit 0f1c691
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 23 deletions.
4 changes: 1 addition & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
### Added
- [`no-anonymous-default-export`] rule: report anonymous default exports ([#712], thanks [@duncanbeevers]).
- Add new value to `order`'s `newlines-between` option to allow newlines inside import groups ([#627], [#628], thanks [@giodamelio])
- [`exports-last`] lints that export statements are at the end of the file ([#620] + [#632])

### Changed
- [`no-extraneous-dependencies`]: use `read-pkg-up` to simplify finding + loading `package.json` ([#680], thanks [@wtgtybhertgeghgtwtg])
Expand Down Expand Up @@ -35,9 +36,6 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
- Properly report [`newline-after-import`] when next line is a decorator
- Fixed documentation for the default values for the [`order`] rule ([#601])

### Added
- [`exports-last`] lints that export statements are at the end of the file ([#620] + [#632])

## [2.0.1] - 2016-10-06
### Fixed
- Fixed code that relied on removed dependencies. ([#604])
Expand Down
4 changes: 3 additions & 1 deletion docs/rules/exports-last.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# exports-last

This rule reports all export declaration which come before any non-export statements.
This rule enforces that all exports are declared at the bottom of the file. This rule will report any export declarations that comes before any non-export statements.


## This will be reported
Expand All @@ -26,6 +26,8 @@ const str = 'foo'
## This will not be reported

```JS
const arr = ['bar']

export const bool = true

export default bool
Expand Down
30 changes: 17 additions & 13 deletions src/rules/exports-last.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
const isExportStatement = ({ type }) =>
type === 'ExportDefaultDeclaration'
|| type === 'ExportNamedDeclaration'
|| type === 'ExportAllDeclaration'
function isNonExportStatement({ type }) {
return type !== 'ExportDefaultDeclaration' &&
type !== 'ExportNamedDeclaration' &&
type !== 'ExportAllDeclaration'
}

const rule = {
create(context) {
module.exports = {
create: function (context) {
return {
Program({ body }) {
const firstExportStatementIndex = body.findIndex(isExportStatement)
Program: function ({ body }) {
const lastNonExportStatementIndex = body.reduce(function findLastIndex(acc, item, index) {
if (isNonExportStatement(item)) {
return index
}
return acc
}, -1)

if (firstExportStatementIndex !== -1) {
body.slice(firstExportStatementIndex).forEach((node) => {
if (!isExportStatement(node)) {
if (lastNonExportStatementIndex !== -1) {
body.slice(0, lastNonExportStatementIndex).forEach(function checkNonExport(node) {
if (!isNonExportStatement(node)) {
context.report({
node,
message: 'Export statements should appear at the end of the file',
Expand All @@ -23,5 +29,3 @@ const rule = {
}
},
}

export default rule
19 changes: 13 additions & 6 deletions tests/src/rules/exports-last.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ import rule from 'rules/exports-last'

const ruleTester = new RuleTester()

const errors = ['Export statements should appear at the end of the file']
const error = type => ({
ruleId: 'exports-last',
message: 'Export statements should appear at the end of the file',
type
});

ruleTester.run('exports-last', rule, {
valid: [
// Empty file
test({
code: '',
code: '// comment',
}),
test({
// No exports
Expand Down Expand Up @@ -82,23 +86,23 @@ ruleTester.run('exports-last', rule, {
export default 'bar'
const bar = true
`,
errors,
errors: [error('ExportDefaultDeclaration')],
}),
// Named export before variable declaration
test({
code: `
export const foo = 'bar'
const bar = true
`,
errors,
errors: [error('ExportNamedDeclaration')],
}),
// Export all before variable declaration
test({
code: `
export * from './foo'
const bar = true
`,
errors,
errors: [error('ExportAllDeclaration')],
}),
// Many exports arround variable declaration
test({
Expand All @@ -111,7 +115,10 @@ ruleTester.run('exports-last', rule, {
export const even = 'count'
export const how = 'many'
`,
errors,
errors: [
error('ExportDefaultDeclaration'),
error('ExportNamedDeclaration'),
],
}),
],
})

0 comments on commit 0f1c691

Please sign in to comment.