Skip to content

Commit 7e00bb2

Browse files
committed
Add rule exports-last
exports-last will check that all export statements are at the end of the file Closes #620
1 parent 2cbd801 commit 7e00bb2

File tree

3 files changed

+124
-0
lines changed

3 files changed

+124
-0
lines changed

Diff for: src/index.js

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ export const rules = {
2929
'unambiguous': require('./rules/unambiguous'),
3030
'no-unassigned-import': require('./rules/no-unassigned-import'),
3131

32+
// export
33+
'exports-last': require('./rules/exports-last'),
34+
3235
// metadata-based
3336
'no-deprecated': require('./rules/no-deprecated'),
3437

Diff for: src/rules/exports-last.js

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
function isExportStatement({ type }) {
2+
// ES Module export statements
3+
if (type === 'ExportDefaultDeclaration' || type === 'ExportNamedDeclaration') {
4+
return true
5+
6+
// CommonJS export statements
7+
} else if (type === 'ExpressionStatement') {
8+
// TODO
9+
}
10+
11+
return false
12+
}
13+
14+
const rule = {
15+
create(context) {
16+
return {
17+
Program({ body }) {
18+
const lastNonExportStatement = body.reduce((acc, node, index) => {
19+
if (isExportStatement(node)) {
20+
return acc
21+
}
22+
return index
23+
}, 0)
24+
25+
body.forEach((node, index) => {
26+
if (isExportStatement(node) && index < lastNonExportStatement) {
27+
28+
context.report({
29+
node,
30+
message: 'Export statements should appear at the end of the file',
31+
})
32+
}
33+
})
34+
},
35+
}
36+
},
37+
}
38+
39+
export default rule

Diff for: tests/src/rules/exports-last.js

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { test } from '../utils'
2+
3+
import { RuleTester } from 'eslint'
4+
import rule from 'rules/exports-last'
5+
6+
const ruleTester = new RuleTester()
7+
8+
const errors = ['Export statements should appear at the end of the file']
9+
10+
ruleTester.run('exports-last', rule, {
11+
valid: [
12+
test({
13+
code: `
14+
const foo = 'bar';
15+
const bar = 'baz';
16+
`,
17+
}),
18+
test({
19+
code: `
20+
const foo = 'bar';
21+
export {foo};
22+
`,
23+
}),
24+
test({
25+
code: `
26+
const foo = 'bar';
27+
export default foo;
28+
`,
29+
}),
30+
test({
31+
code: `
32+
const foo = 'bar';
33+
export default foo;
34+
export const bar = true;
35+
`,
36+
}),
37+
// test({
38+
// code: `
39+
// const foo = 'bar';
40+
// module.exports = foo
41+
// `,
42+
// }),
43+
// test({
44+
// code: `
45+
// const foo = 'bar';
46+
// module.exports = foo;
47+
// exports.bar = true
48+
// `,
49+
// }),
50+
51+
],
52+
invalid: [
53+
test({
54+
code: `
55+
export default 'bar';
56+
const bar = true;
57+
`,
58+
errors,
59+
}),
60+
test({
61+
code: `
62+
export const foo = 'bar';
63+
const bar = true;
64+
`,
65+
errors,
66+
}),
67+
// test({
68+
// code: `
69+
// module.exports = 'bar';
70+
// console.log('hi');
71+
// `,
72+
// errors,
73+
// }),
74+
// test({
75+
// code: `
76+
// exports.foo = 'bar';
77+
// const bar = true;
78+
// `,
79+
// errors,
80+
// }),
81+
],
82+
})

0 commit comments

Comments
 (0)