-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
484 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# Enforce a convention in module import order | ||
|
||
Enforce a convention in the order of `require()` / `import` statements. The order is as shown in the following example: | ||
|
||
```js | ||
// 1. node "builtins" | ||
import fs from 'fs'; | ||
import path from 'path'; | ||
// 2. "external" modules | ||
import _ from 'lodash'; | ||
import chalk from 'chalk'; | ||
// 3. modules from a "parent" directory | ||
import foo from '../foo'; | ||
import qux from '../../foo/qux'; | ||
// 4. "sibling" modules from the same or a sibling's directory | ||
import bar from './bar'; | ||
import baz from './bar/baz'; | ||
// 5. "index" of the current directory | ||
import main from './'; | ||
``` | ||
|
||
Unassigned imports are not accounted for, as the order they are imported in may be important. | ||
|
||
|
||
## Fail | ||
|
||
```js | ||
import _ from 'lodash'; | ||
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` | ||
``` | ||
|
||
|
||
## Pass | ||
|
||
```js | ||
import path from 'path'; | ||
import _ from 'lodash'; | ||
|
||
// ----- | ||
|
||
var path = require('path'); | ||
var _ = require('lodash'); | ||
|
||
// ----- | ||
|
||
// Allowed as ̀`babel-register` is not assigned. | ||
require('babel-register'); | ||
var path = require('path'); | ||
``` | ||
|
||
## Options | ||
|
||
This rule supports the following options: | ||
|
||
`order`: The order to respect. It needs to contain only and all of the following elements: `"builtin", "external", "parent", "sibling", "index"`, which is the default value. | ||
|
||
You can set the options like this: | ||
|
||
```js | ||
"import-order/import-order": ["error", {"order": ["index", "sibling", "parent", "external", "builtin"]}] | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
'use strict' | ||
|
||
import find from 'lodash.find' | ||
import importType from '../core/importType' | ||
import isStaticRequire from '../core/staticRequire' | ||
|
||
const defaultOrder = ['builtin', 'external', 'parent', 'sibling', 'index'] | ||
|
||
// REPORTING | ||
|
||
function reverse(array) { | ||
return array.map(function (v) { | ||
return { | ||
name: v.name, | ||
rank: -v.rank, | ||
node: v.node, | ||
} | ||
}).reverse() | ||
} | ||
|
||
function findOutOfOrder(imported) { | ||
if (imported.length === 0) { | ||
return [] | ||
} | ||
let maxSeenRankNode = imported[0] | ||
return imported.filter(function (importedModule) { | ||
const res = importedModule.rank < maxSeenRankNode.rank | ||
if (maxSeenRankNode.rank < importedModule.rank) { | ||
maxSeenRankNode = importedModule | ||
} | ||
return res | ||
}) | ||
} | ||
|
||
function report(context, imported, outOfOrder, order) { | ||
outOfOrder.forEach(function (imp) { | ||
const found = find(imported, function hasHigherRank(importedItem) { | ||
return importedItem.rank > imp.rank | ||
}) | ||
context.report(imp.node, '`' + imp.name + '` import should occur ' + order + | ||
' import of `' + found.name + '`') | ||
}) | ||
} | ||
|
||
function makeReport(context, imported) { | ||
const outOfOrder = findOutOfOrder(imported) | ||
if (!outOfOrder.length) { | ||
return | ||
} | ||
// There are things to report. Try to minimize the number of reported errors. | ||
const reversedImported = reverse(imported) | ||
const reversedOrder = findOutOfOrder(reversedImported) | ||
if (reversedOrder.length < outOfOrder.length) { | ||
report(context, reversedImported, reversedOrder, 'after') | ||
return | ||
} | ||
report(context, imported, outOfOrder, 'before') | ||
} | ||
|
||
// DETECTING | ||
|
||
function computeRank(context, order, name) { | ||
return order.indexOf(importType(name, context)) | ||
} | ||
|
||
function registerNode(context, node, name, order, imported) { | ||
const rank = computeRank(context, order, name) | ||
if (rank !== -1) { | ||
imported.push({name: name, rank: rank, node: node}) | ||
} | ||
} | ||
|
||
function isInVariableDeclarator(node) { | ||
return node && | ||
(node.type === 'VariableDeclarator' || isInVariableDeclarator(node.parent)) | ||
} | ||
|
||
module.exports = function importOrderRule (context) { | ||
const options = context.options[0] || {} | ||
const order = options.order || defaultOrder | ||
let imported = [] | ||
let level = 0 | ||
|
||
function incrementLevel() { | ||
level++ | ||
} | ||
function decrementLevel() { | ||
level-- | ||
} | ||
|
||
return { | ||
ImportDeclaration: function handleImports(node) { | ||
if (node.specifiers.length) { // Ignoring unassigned imports | ||
const name = node.source.value | ||
registerNode(context, node, name, order, imported) | ||
} | ||
}, | ||
CallExpression: function handleRequires(node) { | ||
if (level !== 0 || !isStaticRequire(node) || !isInVariableDeclarator(node.parent)) { | ||
return | ||
} | ||
const name = node.arguments[0].value | ||
registerNode(context, node, name, order, imported) | ||
}, | ||
'Program:exit': function reportAndReset() { | ||
makeReport(context, imported) | ||
imported = [] | ||
}, | ||
FunctionDeclaration: incrementLevel, | ||
FunctionExpression: incrementLevel, | ||
ArrowFunctionExpression: incrementLevel, | ||
BlockStatement: incrementLevel, | ||
'FunctionDeclaration:exit': decrementLevel, | ||
'FunctionExpression:exit': decrementLevel, | ||
'ArrowFunctionExpression:exit': decrementLevel, | ||
'BlockStatement:exit': decrementLevel, | ||
} | ||
} | ||
|
||
module.exports.schema = [ | ||
{ | ||
type: 'object', | ||
properties: { | ||
order: { | ||
type: 'array', | ||
uniqueItems: true, | ||
length: 5, | ||
items: { | ||
enum: defaultOrder, | ||
}, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.