Skip to content

Commit

Permalink
order: enforce imports being before require
Browse files Browse the repository at this point in the history
  • Loading branch information
jfmengels committed Apr 25, 2016
1 parent 039a77b commit 38f3935
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 19 deletions.
15 changes: 14 additions & 1 deletion docs/rules/order.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ import baz from './bar/baz';
import main from './';
```

Unassigned imports are not accounted for, as the order they are imported in may be important.
Unassigned imports are ignored, as the order they are imported in may be important.

Statements using the ES6 `import` syntax must appear before any `require()` statements.


## Fail
Expand All @@ -35,6 +37,11 @@ import path from 'path'; // `path` import should occur before import of `lodash`

var _ = require('lodash');
var path = require('path'); // `path` import should occur before import of `lodash`

// -----

var path = require('path');
import foo from './foo'; // `import` statements must be before `require` statement
```


Expand All @@ -54,6 +61,12 @@ var _ = require('lodash');
// Allowed as ̀`babel-register` is not assigned.
require('babel-register');
var path = require('path');

// -----

// Allowed as `import` must be before `require`
import foo from './foo';
var path = require('path');
```

## Options
Expand Down
15 changes: 8 additions & 7 deletions src/rules/order.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,15 @@ function makeReport(context, imported) {

// DETECTING

function computeRank(context, ranks, name) {
return ranks[importType(name, context)]
function computeRank(context, ranks, name, type) {
return ranks[importType(name, context)] +
(type === 'import' ? 0 : 100)
}

function registerNode(context, node, name, ranks, imported) {
const rank = computeRank(context, ranks, name)
function registerNode(context, node, name, type, ranks, imported) {
const rank = computeRank(context, ranks, name, type)
if (rank !== -1) {
imported.push({name: name, rank: rank, node: node})
imported.push({name, rank, node})
}
}

Expand Down Expand Up @@ -136,15 +137,15 @@ module.exports = function importOrderRule (context) {
ImportDeclaration: function handleImports(node) {
if (node.specifiers.length) { // Ignoring unassigned imports
const name = node.source.value
registerNode(context, node, name, ranks, imported)
registerNode(context, node, name, 'import', ranks, imported)
}
},
CallExpression: function handleRequires(node) {
if (level !== 0 || !isStaticRequire(node) || !isInVariableDeclarator(node.parent)) {
return
}
const name = node.arguments[0].value
registerNode(context, node, name, ranks, imported)
registerNode(context, node, name, 'require', ranks, imported)
},
'Program:exit': function reportAndReset() {
makeReport(context, imported)
Expand Down
50 changes: 39 additions & 11 deletions tests/src/rules/order.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,6 @@ ruleTester.run('order', rule, {
import sibling, {foo3} from './foo';
import index from './';`,
}),
// Default order using both require and import
test({
code: `
var fs = require('fs');
import async, {foo1} from 'async';
var relParent1 = require('../foo');
import relParent2, {foo2} from '../foo/bar';
var relParent3 = require('../');
import sibling, {foo3} from './foo';
var index = require('./');`,
}),
// Multiple module of the same rank next to each other
test({
code: `
Expand Down Expand Up @@ -159,6 +148,18 @@ ruleTester.run('order', rule, {
// missing 'builtin'
]}],
}),
// Mixing require and import should have import up top
test({
code: `
import async, {foo1} from 'async';
import relParent2, {foo2} from '../foo/bar';
import sibling, {foo3} from './foo';
var fs = require('fs');
var relParent1 = require('../foo');
var relParent3 = require('../');
var index = require('./');
`,
}),
],
invalid: [
// builtin before external module (require)
Expand Down Expand Up @@ -385,5 +386,32 @@ ruleTester.run('order', rule, {
message: 'Incorrect configuration of the rule: `parent` is duplicated',
}],
}),
// Mixing require and import should have import up top
test({
code: `
import async, {foo1} from 'async';
import relParent2, {foo2} from '../foo/bar';
var fs = require('fs');
var relParent1 = require('../foo');
var relParent3 = require('../');
import sibling, {foo3} from './foo';
var index = require('./');
`,
errors: [{
ruleId: 'order',
message: '`./foo` import should occur before import of `fs`',
}],
}),
test({
code: `
var fs = require('fs');
import async, {foo1} from 'async';
import relParent2, {foo2} from '../foo/bar';
`,
errors: [{
ruleId: 'order',
message: '`fs` import should occur after import of `../foo/bar`',
}],
}),
],
})

0 comments on commit 38f3935

Please sign in to comment.