169 lines
17 KiB
JavaScript
169 lines
17 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
var _staticRequire = require('../core/staticRequire');
|
||
|
|
||
|
var _staticRequire2 = _interopRequireDefault(_staticRequire);
|
||
|
|
||
|
var _docsUrl = require('../docsUrl');
|
||
|
|
||
|
var _docsUrl2 = _interopRequireDefault(_docsUrl);
|
||
|
|
||
|
var _debug = require('debug');
|
||
|
|
||
|
var _debug2 = _interopRequireDefault(_debug);
|
||
|
|
||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||
|
|
||
|
const log = (0, _debug2.default)('eslint-plugin-import:rules:newline-after-import');
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Rule Definition
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
/**
|
||
|
* @fileoverview Rule to enforce new line after import not followed by another import.
|
||
|
* @author Radek Benkel
|
||
|
*/
|
||
|
|
||
|
function containsNodeOrEqual(outerNode, innerNode) {
|
||
|
return outerNode.range[0] <= innerNode.range[0] && outerNode.range[1] >= innerNode.range[1];
|
||
|
}
|
||
|
|
||
|
function getScopeBody(scope) {
|
||
|
if (scope.block.type === 'SwitchStatement') {
|
||
|
log('SwitchStatement scopes not supported');
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
const body = scope.block.body;
|
||
|
|
||
|
if (body && body.type === 'BlockStatement') {
|
||
|
return body.body;
|
||
|
}
|
||
|
|
||
|
return body;
|
||
|
}
|
||
|
|
||
|
function findNodeIndexInScopeBody(body, nodeToFind) {
|
||
|
return body.findIndex(node => containsNodeOrEqual(node, nodeToFind));
|
||
|
}
|
||
|
|
||
|
function getLineDifference(node, nextNode) {
|
||
|
return nextNode.loc.start.line - node.loc.end.line;
|
||
|
}
|
||
|
|
||
|
function isClassWithDecorator(node) {
|
||
|
return node.type === 'ClassDeclaration' && node.decorators && node.decorators.length;
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
meta: {
|
||
|
docs: {
|
||
|
url: (0, _docsUrl2.default)('newline-after-import')
|
||
|
},
|
||
|
schema: [{
|
||
|
'type': 'object',
|
||
|
'properties': {
|
||
|
'count': {
|
||
|
'type': 'integer',
|
||
|
'minimum': 1
|
||
|
}
|
||
|
},
|
||
|
'additionalProperties': false
|
||
|
}],
|
||
|
fixable: 'whitespace'
|
||
|
},
|
||
|
create: function (context) {
|
||
|
let level = 0;
|
||
|
const requireCalls = [];
|
||
|
|
||
|
function checkForNewLine(node, nextNode, type) {
|
||
|
if (isClassWithDecorator(nextNode)) {
|
||
|
nextNode = nextNode.decorators[0];
|
||
|
}
|
||
|
|
||
|
const options = context.options[0] || { count: 1 };
|
||
|
const lineDifference = getLineDifference(node, nextNode);
|
||
|
const EXPECTED_LINE_DIFFERENCE = options.count + 1;
|
||
|
|
||
|
if (lineDifference < EXPECTED_LINE_DIFFERENCE) {
|
||
|
let column = node.loc.start.column;
|
||
|
|
||
|
if (node.loc.start.line !== node.loc.end.line) {
|
||
|
column = 0;
|
||
|
}
|
||
|
|
||
|
context.report({
|
||
|
loc: {
|
||
|
line: node.loc.end.line,
|
||
|
column
|
||
|
},
|
||
|
message: `Expected ${options.count} empty line${options.count > 1 ? 's' : ''} \
|
||
|
after ${type} statement not followed by another ${type}.`,
|
||
|
fix: fixer => fixer.insertTextAfter(node, '\n'.repeat(EXPECTED_LINE_DIFFERENCE - lineDifference))
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function incrementLevel() {
|
||
|
level++;
|
||
|
}
|
||
|
function decrementLevel() {
|
||
|
level--;
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
ImportDeclaration: function (node) {
|
||
|
const parent = node.parent;
|
||
|
|
||
|
const nodePosition = parent.body.indexOf(node);
|
||
|
const nextNode = parent.body[nodePosition + 1];
|
||
|
|
||
|
if (nextNode && nextNode.type !== 'ImportDeclaration') {
|
||
|
checkForNewLine(node, nextNode, 'import');
|
||
|
}
|
||
|
},
|
||
|
CallExpression: function (node) {
|
||
|
if ((0, _staticRequire2.default)(node) && level === 0) {
|
||
|
requireCalls.push(node);
|
||
|
}
|
||
|
},
|
||
|
'Program:exit': function () {
|
||
|
log('exit processing for', context.getFilename());
|
||
|
const scopeBody = getScopeBody(context.getScope());
|
||
|
log('got scope:', scopeBody);
|
||
|
|
||
|
requireCalls.forEach(function (node, index) {
|
||
|
const nodePosition = findNodeIndexInScopeBody(scopeBody, node);
|
||
|
log('node position in scope:', nodePosition);
|
||
|
|
||
|
const statementWithRequireCall = scopeBody[nodePosition];
|
||
|
const nextStatement = scopeBody[nodePosition + 1];
|
||
|
const nextRequireCall = requireCalls[index + 1];
|
||
|
|
||
|
if (nextRequireCall && containsNodeOrEqual(statementWithRequireCall, nextRequireCall)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (nextStatement && (!nextRequireCall || !containsNodeOrEqual(nextStatement, nextRequireCall))) {
|
||
|
|
||
|
checkForNewLine(statementWithRequireCall, nextStatement, 'require');
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
FunctionDeclaration: incrementLevel,
|
||
|
FunctionExpression: incrementLevel,
|
||
|
ArrowFunctionExpression: incrementLevel,
|
||
|
BlockStatement: incrementLevel,
|
||
|
ObjectExpression: incrementLevel,
|
||
|
Decorator: incrementLevel,
|
||
|
'FunctionDeclaration:exit': decrementLevel,
|
||
|
'FunctionExpression:exit': decrementLevel,
|
||
|
'ArrowFunctionExpression:exit': decrementLevel,
|
||
|
'BlockStatement:exit': decrementLevel,
|
||
|
'ObjectExpression:exit': decrementLevel,
|
||
|
'Decorator:exit': decrementLevel
|
||
|
};
|
||
|
}
|
||
|
};
|
||
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInJ1bGVzL25ld2xpbmUtYWZ0ZXItaW1wb3J0LmpzIl0sIm5hbWVzIjpbImxvZyIsImNvbnRhaW5zTm9kZU9yRXF1YWwiLCJvdXRlck5vZGUiLCJpbm5lck5vZGUiLCJyYW5nZSIsImdldFNjb3BlQm9keSIsInNjb3BlIiwiYmxvY2siLCJ0eXBlIiwiYm9keSIsImZpbmROb2RlSW5kZXhJblNjb3BlQm9keSIsIm5vZGVUb0ZpbmQiLCJmaW5kSW5kZXgiLCJub2RlIiwiZ2V0TGluZURpZmZlcmVuY2UiLCJuZXh0Tm9kZSIsImxvYyIsInN0YXJ0IiwibGluZSIsImVuZCIsImlzQ2xhc3NXaXRoRGVjb3JhdG9yIiwiZGVjb3JhdG9ycyIsImxlbmd0aCIsIm1vZHVsZSIsImV4cG9ydHMiLCJtZXRhIiwiZG9jcyIsInVybCIsInNjaGVtYSIsImZpeGFibGUiLCJjcmVhdGUiLCJjb250ZXh0IiwibGV2ZWwiLCJyZXF1aXJlQ2FsbHMiLCJjaGVja0Zvck5ld0xpbmUiLCJvcHRpb25zIiwiY291bnQiLCJsaW5lRGlmZmVyZW5jZSIsIkVYUEVDVEVEX0xJTkVfRElGRkVSRU5DRSIsImNvbHVtbiIsInJlcG9ydCIsIm1lc3NhZ2UiLCJmaXgiLCJmaXhlciIsImluc2VydFRleHRBZnRlciIsInJlcGVhdCIsImluY3JlbWVudExldmVsIiwiZGVjcmVtZW50TGV2ZWwiLCJJbXBvcnREZWNsYXJhdGlvbiIsInBhcmVudCIsIm5vZGVQb3NpdGlvbiIsImluZGV4T2YiLCJDYWxsRXhwcmVzc2lvbiIsInB1c2giLCJnZXRGaWxlbmFtZSIsInNjb3BlQm9keSIsImdldFNjb3BlIiwiZm9yRWFjaCIsImluZGV4Iiwic3RhdGVtZW50V2l0aFJlcXVpcmVDYWxsIiwibmV4dFN0YXRlbWVudCIsIm5leHRSZXF1aXJlQ2FsbCIsIkZ1bmN0aW9uRGVjbGFyYXRpb24iLCJGdW5jdGlvbkV4cHJlc3Npb24iLCJBcnJvd0Z1bmN0aW9uRXhwcmVzc2lvbiIsIkJsb2NrU3RhdGVtZW50IiwiT2JqZWN0RXhwcmVzc2lvbiIsIkRlY29yYXRvciJdLCJtYXBwaW5ncyI6Ijs7QUFLQTs7OztBQUNBOzs7O0FBRUE7Ozs7OztBQUNBLE1BQU1BLE1BQU0scUJBQU0saURBQU4sQ0FBWjs7QUFFQTtBQUNBO0FBQ0E7O0FBYkE7Ozs7O0FBZUEsU0FBU0MsbUJBQVQsQ0FBNkJDLFNBQTdCLEVBQXdDQyxTQUF4QyxFQUFtRDtBQUMvQyxTQUFPRCxVQUFVRSxLQUFWLENBQWdCLENBQWhCLEtBQXNCRCxVQUFVQyxLQUFWLENBQWdCLENBQWhCLENBQXRCLElBQTRDRixVQUFVRSxLQUFWLENBQWdCLENBQWhCLEtBQXNCRCxVQUFVQyxLQUFWLENBQWdCLENBQWhCLENBQXpFO0FBQ0g7O0FBRUQsU0FBU0MsWUFBVCxDQUFzQkMsS0FBdEIsRUFBNkI7QUFDekIsTUFBSUEsTUFBTUMsS0FBTixDQUFZQyxJQUFaLEtBQXFCLGlCQUF6QixFQUE0QztBQUMxQ1IsUUFBSSxzQ0FBSjtBQUNBLFdBQU8sSUFBUDtBQUNEOztBQUp3QixRQU1qQlMsSUFOaUIsR0FNUkgsTUFBTUMsS0FORSxDQU1qQkUsSUFOaUI7O0FBT3pCLE1BQUlBLFFBQVFBLEtBQUtELElBQUwsS0FBYyxnQkFBMUIsRUFBNEM7QUFDeEMsV0FBT0MsS0FBS0EsSUFBWjtBQUNIOztBQUVELFNBQU9BLElBQVA7QUFDSDs7QUFFRCxTQUFTQyx3QkFBVCxDQUFrQ0QsSUFBbEMsRUFBd0NFLFVBQXhDLEVBQW9EO0FBQ2hELFNBQU9GLEtBQUtHLFNBQUwsQ0FBZ0JDLElBQUQsSUFBVVosb0JBQW9CWSxJQUFwQixFQUEwQkYsVUFBMUIsQ0FBekIsQ0FBUDtBQUNIOztBQUVELFNBQVNHLGlCQUFULENBQTJCRCxJQUEzQixFQUFpQ0UsUUFBakMsRUFBMkM7QUFDekMsU0FBT0EsU0FBU0MsR0FBVCxDQUFhQyxLQUFiLENBQW1CQyxJQUFuQixHQUEwQkwsS0FBS0csR0FBTCxDQUFTRyxHQUFULENBQWFELElBQTlDO0FBQ0Q7O0FBRUQsU0FBU0Usb0JBQVQsQ0FBOEJQLElBQTlCLEVBQW9DO0FBQ2xDLFNBQU9BLEtBQUtMLElBQUwsS0FBYyxrQkFBZCxJQUFvQ0ssS0FBS1EsVUFBekMsSUFBdURSLEtBQUtRLFVBQUwsQ0FBZ0JDLE1BQTlFO0FBQ0Q7O0FBRURDLE9BQU9DLE9BQVAsR0FBaUI7QUFDZkMsUUFBTTtBQUNKQyxVQUFNO0FBQ0pDLFdBQUssdUJBQVEsc0JBQVI7QUFERCxLQURGO0FBSUpDLFlBQVEsQ0FDTjtBQUNFLGNBQVEsUUFEVjtBQUVFLG9CQUFjO0FBQ1osaUJBQVM7QUFDUCxrQkFBUSxTQUREO0FBRVAscUJBQVc7QUFGSjtBQURHLE9BRmhCO0FBUUUsOEJBQXdCO0FBUjFCLEtBRE0sQ0FKSjtBQWdCSkMsYUFBUztBQWhCTCxHQURTO0FBbUJmQyxVQUFRLFVBQVVDLE9BQVYsRUFBbUI7QUFDekIsUUFBSUMsUUFBUSxDQUFaO0FBQ0EsVUFBTUMsZUFBZSxFQUFyQjs7QUFFQSxhQUFTQyxlQUFULENBQXlCckIsSUFBekIsRUFBK0JFLFFBQS9CLEVBQXlDUCxJQUF6QyxFQUErQztBQUM3QyxVQUFJWSxxQkFBcUJMLFFBQXJCLENBQUosRUFBb0M7QUFDbENBLG1CQUFXQSxTQUFTTSxVQUFULENBQW9CLENBQXBCLENBQVg7QUFDRDs7QUFFRCxZQUFNYyxVQUFVSixRQUFRSSxPQUFSLENBQWdCLENBQWhCLEtBQXNCLEVBQUVDLE9BQU8sQ0FBVCxFQUF0QztBQUNBLFlBQU1DLGlCQUFpQnZCLGtCQUFrQkQsSUFBbEIsRUFBd0JFLFFBQXhCLENBQXZCO0FBQ0EsWUFBTXVCLDJCQUEyQkgsUUFBUUMsS0FBUixHQUFnQixDQUFqRDs7QUFFQSxVQUFJQyxpQkFBaUJDLHdCQUFyQixFQUErQztBQUM3QyxZQUFJQyxTQUFTMUIsS0FBS0csR0FBTCxDQUFTQyxLQUFULENBQWVzQixNQUE1Qjs7QUFFQSxZQUFJMUIsS0FBS0csR0FBTCxDQUFTQyxLQUFULENBQWVDLElBQWYsS0FBd0JMLEtBQUtHLEdBQUwsQ0FBU0csR0FBVCxDQUFhRCxJQUF6QyxFQUErQztBQUM3Q3FCLG1CQUFTLENBQVQ7QUFDRDs7QUFFRFIsZ0JBQVFTLE1BQVIsQ0FBZTtBQUNieEIsZUFBSztBQUNIRSxrQkFBTUwsS0FBS0csR0FBTCxDQUFTRyxHQUFULENBQWFELElBRGhCO0FBRUhxQjtBQUZHLFdBRFE7QUFLYkUsbUJBQVUsWUFBV04sUUFBUUMsS0FBTSxjQUFhRCxRQUFRQyxLQUFSLEdBQWdCLENBQWhCLEdBQW9CLEdBQXBCLEdBQTBCLEVBQUc7UUFDL0U1QixJQUFLLHNDQUFxQ0EsSUFBSyxHQU5oQztBQU9ia0MsZUFBS0MsU0FBU0EsTUFBTUMsZUFBTixDQUNaL0IsSUFEWSxFQUVaLEtBQUtnQyxNQUFMLENBQVlQLDJCQUEyQkQsY0FBdkMsQ0FGWTtBQVBELFNBQWY7QUFZRDt
|