249 lines
30 KiB
JavaScript
249 lines
30 KiB
JavaScript
|
|
'use strict';
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
var _contextCompat = require('eslint-module-utils/contextCompat');
|
||
|
|
|
||
|
|
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 };} /**
|
||
|
|
* @fileoverview Rule to enforce new line after import not followed by another import.
|
||
|
|
* @author Radek Benkel
|
||
|
|
*/var log = (0, _debug2['default'])('eslint-plugin-import:rules:newline-after-import'); //------------------------------------------------------------------------------
|
||
|
|
// Rule Definition
|
||
|
|
//------------------------------------------------------------------------------
|
||
|
|
|
||
|
|
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;
|
||
|
|
}var
|
||
|
|
|
||
|
|
body = scope.block.body;
|
||
|
|
if (body && body.type === 'BlockStatement') {
|
||
|
|
return body.body;
|
||
|
|
}
|
||
|
|
|
||
|
|
return body;
|
||
|
|
}
|
||
|
|
|
||
|
|
function findNodeIndexInScopeBody(body, nodeToFind) {
|
||
|
|
return body.findIndex(function (node) {return 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;
|
||
|
|
}
|
||
|
|
|
||
|
|
function isExportDefaultClass(node) {
|
||
|
|
return node.type === 'ExportDefaultDeclaration' && node.declaration.type === 'ClassDeclaration';
|
||
|
|
}
|
||
|
|
|
||
|
|
function isExportNameClass(node) {
|
||
|
|
|
||
|
|
return node.type === 'ExportNamedDeclaration' && node.declaration && node.declaration.type === 'ClassDeclaration';
|
||
|
|
}
|
||
|
|
|
||
|
|
module.exports = {
|
||
|
|
meta: {
|
||
|
|
type: 'layout',
|
||
|
|
docs: {
|
||
|
|
category: 'Style guide',
|
||
|
|
description: 'Enforce a newline after import statements.',
|
||
|
|
url: (0, _docsUrl2['default'])('newline-after-import') },
|
||
|
|
|
||
|
|
fixable: 'whitespace',
|
||
|
|
schema: [
|
||
|
|
{
|
||
|
|
type: 'object',
|
||
|
|
properties: {
|
||
|
|
count: {
|
||
|
|
type: 'integer',
|
||
|
|
minimum: 1 },
|
||
|
|
|
||
|
|
exactCount: { type: 'boolean' },
|
||
|
|
considerComments: { type: 'boolean' } },
|
||
|
|
|
||
|
|
additionalProperties: false }] },
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
create: function () {function create(context) {
|
||
|
|
var level = 0;
|
||
|
|
var requireCalls = [];
|
||
|
|
var options = Object.assign({
|
||
|
|
count: 1,
|
||
|
|
exactCount: false,
|
||
|
|
considerComments: false },
|
||
|
|
context.options[0]);
|
||
|
|
|
||
|
|
|
||
|
|
function checkForNewLine(node, nextNode, type) {
|
||
|
|
if (isExportDefaultClass(nextNode) || isExportNameClass(nextNode)) {
|
||
|
|
var classNode = nextNode.declaration;
|
||
|
|
|
||
|
|
if (isClassWithDecorator(classNode)) {
|
||
|
|
nextNode = classNode.decorators[0];
|
||
|
|
}
|
||
|
|
} else if (isClassWithDecorator(nextNode)) {
|
||
|
|
nextNode = nextNode.decorators[0];
|
||
|
|
}
|
||
|
|
|
||
|
|
var lineDifference = getLineDifference(node, nextNode);
|
||
|
|
var EXPECTED_LINE_DIFFERENCE = options.count + 1;
|
||
|
|
|
||
|
|
if (
|
||
|
|
lineDifference < EXPECTED_LINE_DIFFERENCE ||
|
||
|
|
options.exactCount && lineDifference !== EXPECTED_LINE_DIFFERENCE)
|
||
|
|
{
|
||
|
|
var 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: column },
|
||
|
|
|
||
|
|
message: 'Expected ' + String(options.count) + ' empty line' + (options.count > 1 ? 's' : '') + ' after ' + String(type) + ' statement not followed by another ' + String(type) + '.',
|
||
|
|
fix: options.exactCount && EXPECTED_LINE_DIFFERENCE < lineDifference ? undefined : function (fixer) {return fixer.insertTextAfter(
|
||
|
|
node,
|
||
|
|
'\n'.repeat(EXPECTED_LINE_DIFFERENCE - lineDifference));} });
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function commentAfterImport(node, nextComment, type) {
|
||
|
|
var lineDifference = getLineDifference(node, nextComment);
|
||
|
|
var EXPECTED_LINE_DIFFERENCE = options.count + 1;
|
||
|
|
|
||
|
|
if (lineDifference < EXPECTED_LINE_DIFFERENCE) {
|
||
|
|
var 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: column },
|
||
|
|
|
||
|
|
message: 'Expected ' + String(options.count) + ' empty line' + (options.count > 1 ? 's' : '') + ' after ' + String(type) + ' statement not followed by another ' + String(type) + '.',
|
||
|
|
fix: options.exactCount && EXPECTED_LINE_DIFFERENCE < lineDifference ? undefined : function (fixer) {return fixer.insertTextAfter(
|
||
|
|
node,
|
||
|
|
'\n'.repeat(EXPECTED_LINE_DIFFERENCE - lineDifference));} });
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function incrementLevel() {
|
||
|
|
level++;
|
||
|
|
}
|
||
|
|
function decrementLevel() {
|
||
|
|
level--;
|
||
|
|
}
|
||
|
|
|
||
|
|
function checkImport(node) {var
|
||
|
|
parent = node.parent;
|
||
|
|
|
||
|
|
if (!parent || !parent.body) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
var nodePosition = parent.body.indexOf(node);
|
||
|
|
var nextNode = parent.body[nodePosition + 1];
|
||
|
|
var endLine = node.loc.end.line;
|
||
|
|
var nextComment = void 0;
|
||
|
|
|
||
|
|
if (typeof parent.comments !== 'undefined' && options.considerComments) {
|
||
|
|
nextComment = parent.comments.find(function (o) {return o.loc.start.line >= endLine && o.loc.start.line <= endLine + options.count + 1;});
|
||
|
|
}
|
||
|
|
|
||
|
|
// skip "export import"s
|
||
|
|
if (node.type === 'TSImportEqualsDeclaration' && node.isExport) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (nextComment && typeof nextComment !== 'undefined') {
|
||
|
|
commentAfterImport(node, nextComment, 'import');
|
||
|
|
} else if (nextNode && nextNode.type !== 'ImportDeclaration' && (nextNode.type !== 'TSImportEqualsDeclaration' || nextNode.isExport)) {
|
||
|
|
checkForNewLine(node, nextNode, 'import');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
ImportDeclaration: checkImport,
|
||
|
|
TSImportEqualsDeclaration: checkImport,
|
||
|
|
CallExpression: function () {function CallExpression(node) {
|
||
|
|
if ((0, _staticRequire2['default'])(node) && level === 0) {
|
||
|
|
requireCalls.push(node);
|
||
|
|
}
|
||
|
|
}return CallExpression;}(),
|
||
|
|
'Program:exit': function () {function ProgramExit(node) {
|
||
|
|
log('exit processing for', (0, _contextCompat.getPhysicalFilename)(context));
|
||
|
|
var scopeBody = getScopeBody((0, _contextCompat.getScope)(context, node));
|
||
|
|
log('got scope:', scopeBody);
|
||
|
|
|
||
|
|
requireCalls.forEach(function (node, index) {
|
||
|
|
var nodePosition = findNodeIndexInScopeBody(scopeBody, node);
|
||
|
|
log('node position in scope:', nodePosition);
|
||
|
|
|
||
|
|
var statementWithRequireCall = scopeBody[nodePosition];
|
||
|
|
var nextStatement = scopeBody[nodePosition + 1];
|
||
|
|
var nextRequireCall = requireCalls[index + 1];
|
||
|
|
|
||
|
|
if (nextRequireCall && containsNodeOrEqual(statementWithRequireCall, nextRequireCall)) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (
|
||
|
|
nextStatement && (
|
||
|
|
!nextRequireCall ||
|
||
|
|
!containsNodeOrEqual(nextStatement, nextRequireCall)))
|
||
|
|
|
||
|
|
{
|
||
|
|
var nextComment = void 0;
|
||
|
|
if (typeof statementWithRequireCall.parent.comments !== 'undefined' && options.considerComments) {
|
||
|
|
var endLine = node.loc.end.line;
|
||
|
|
nextComment = statementWithRequireCall.parent.comments.find(function (o) {return o.loc.start.line >= endLine && o.loc.start.line <= endLine + options.count + 1;});
|
||
|
|
}
|
||
|
|
|
||
|
|
if (nextComment && typeof nextComment !== 'undefined') {
|
||
|
|
|
||
|
|
commentAfterImport(statementWithRequireCall, nextComment, 'require');
|
||
|
|
} else {
|
||
|
|
checkForNewLine(statementWithRequireCall, nextStatement, 'require');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}return ProgramExit;}(),
|
||
|
|
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 };
|
||
|
|
|
||
|
|
}return create;}() };
|
||
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydWxlcy9uZXdsaW5lLWFmdGVyLWltcG9ydC5qcyJdLCJuYW1lcyI6WyJsb2ciLCJjb250YWluc05vZGVPckVxdWFsIiwib3V0ZXJOb2RlIiwiaW5uZXJOb2RlIiwicmFuZ2UiLCJnZXRTY29wZUJvZHkiLCJzY29wZSIsImJsb2NrIiwidHlwZSIsImJvZHkiLCJmaW5kTm9kZUluZGV4SW5TY29wZUJvZHkiLCJub2RlVG9GaW5kIiwiZmluZEluZGV4Iiwibm9kZSIsImdldExpbmVEaWZmZXJlbmNlIiwibmV4dE5vZGUiLCJsb2MiLCJzdGFydCIsImxpbmUiLCJlbmQiLCJpc0NsYXNzV2l0aERlY29yYXRvciIsImRlY29yYXRvcnMiLCJsZW5ndGgiLCJpc0V4cG9ydERlZmF1bHRDbGFzcyIsImRlY2xhcmF0aW9uIiwiaXNFeHBvcnROYW1lQ2xhc3MiLCJtb2R1bGUiLCJleHBvcnRzIiwibWV0YSIsImRvY3MiLCJjYXRlZ29yeSIsImRlc2NyaXB0aW9uIiwidXJsIiwiZml4YWJsZSIsInNjaGVtYSIsInByb3BlcnRpZXMiLCJjb3VudCIsIm1pbmltdW0iLCJleGFjdENvdW50IiwiY29uc2lkZXJDb21tZW50cyIsImFkZGl0aW9uYWxQcm9wZXJ0aWVzIiwiY3JlYXRlIiwiY29udGV4dCIsImxldmVsIiwicmVxdWlyZUNhbGxzIiwib3B0aW9ucyIsImNoZWNrRm9yTmV3TGluZSIsImNsYXNzTm9kZSIsImxpbmVEaWZmZXJlbmNlIiwiRVhQRUNURURfTElORV9ESUZGRVJFTkNFIiwiY29sdW1uIiwicmVwb3J0IiwibWVzc2FnZSIsImZpeCIsInVuZGVmaW5lZCIsImZpeGVyIiwiaW5zZXJ0VGV4dEFmdGVyIiwicmVwZWF0IiwiY29tbWVudEFmdGVySW1wb3J0IiwibmV4dENvbW1lbnQiLCJpbmNyZW1lbnRMZXZlbCIsImRlY3JlbWVudExldmVsIiwiY2hlY2tJbXBvcnQiLCJwYXJlbnQiLCJub2RlUG9zaXRpb24iLCJpbmRleE9mIiwiZW5kTGluZSIsImNvbW1lbnRzIiwiZmluZCIsIm8iLCJpc0V4cG9ydCIsIkltcG9ydERlY2xhcmF0aW9uIiwiVFNJbXBvcnRFcXVhbHNEZWNsYXJhdGlvbiIsIkNhbGxFeHByZXNzaW9uIiwicHVzaCIsInNjb3BlQm9keSIsImZvckVhY2giLCJpbmRleCIsInN0YXRlbWVudFdpdGhSZXF1aXJlQ2FsbCIsIm5leHRTdGF0ZW1lbnQiLCJuZXh0UmVxdWlyZUNhbGwiLCJGdW5jdGlvbkRlY2xhcmF0aW9uIiwiRnVuY3Rpb25FeHByZXNzaW9uIiwiQXJyb3dGdW5jdGlvbkV4cHJlc3Npb24iLCJCbG9ja1N0YXRlbWVudCIsIk9iamVjdEV4cHJlc3Npb24iLCJEZWNvcmF0b3IiXSwibWFwcGluZ3MiOiI7Ozs7O0FBS0E7O0FBRUEsc0Q7QUFDQSxxQzs7QUFFQSw4Qiw2SUFWQTs7OzhLQVdBLElBQU1BLE1BQU0sd0JBQU0saURBQU4sQ0FBWixDLENBRUE7QUFDQTtBQUNBOztBQUVBLFNBQVNDLG1CQUFULENBQTZCQyxTQUE3QixFQUF3Q0MsU0FBeEMsRUFBbUQ7QUFDakQsU0FBT0QsVUFBVUUsS0FBVixDQUFnQixDQUFoQixLQUFzQkQsVUFBVUMsS0FBVixDQUFnQixDQUFoQixDQUF0QixJQUE0Q0YsVUFBVUUsS0FBVixDQUFnQixDQUFoQixLQUFzQkQsVUFBVUMsS0FBVixDQUFnQixDQUFoQixDQUF6RTtBQUNEOztBQUVELFNBQVNDLFlBQVQsQ0FBc0JDLEtBQXRCLEVBQTZCO0FBQzNCLE1BQUlBLE1BQU1DLEtBQU4sQ0FBWUMsSUFBWixLQUFxQixpQkFBekIsRUFBNEM7QUFDMUNSLFFBQUksc0NBQUo7QUFDQSxXQUFPLElBQVA7QUFDRCxHQUowQjs7QUFNbkJTLE1BTm1CLEdBTVZILE1BQU1DLEtBTkksQ0FNbkJFLElBTm1CO0FBTzNCLE1BQUlBLFFBQVFBLEtBQUtELElBQUwsS0FBYyxnQkFBMUIsRUFBNEM7QUFDMUMsV0FBT0MsS0FBS0EsSUFBWjtBQUNEOztBQUVELFNBQU9BLElBQVA7QUFDRDs7QUFFRCxTQUFTQyx3QkFBVCxDQUFrQ0QsSUFBbEMsRUFBd0NFLFVBQXhDLEVBQW9EO0FBQ2xELFNBQU9GLEtBQUtHLFNBQUwsQ0FBZSxVQUFDQyxJQUFELFVBQVVaLG9CQUFvQlksSUFBcEIsRUFBMEJGLFVBQTFCLENBQVYsRUFBZixDQUFQO0FBQ0Q7O0FBRUQsU0FBU0csaUJBQVQsQ0FBMkJELElBQTNCLEVBQWlDRSxRQUFqQyxFQUEyQztBQUN6QyxTQUFPQSxTQUFTQyxHQUFULENBQWFDLEtBQWIsQ0FBbUJDLElBQW5CLEdBQTBCTCxLQUFLRyxHQUFMLENBQVNHLEdBQVQsQ0FBYUQsSUFBOUM7QUFDRDs7QUFFRCxTQUFTRSxvQkFBVCxDQUE4QlAsSUFBOUIsRUFBb0M7QUFDbEMsU0FBT0EsS0FBS0wsSUFBTCxLQUFjLGtCQUFkLElBQW9DSyxLQUFLUSxVQUF6QyxJQUF1RFIsS0FBS1EsVUFBTCxDQUFnQkMsTUFBOUU7QUFDRDs7QUFFRCxTQUFTQyxvQkFBVCxDQUE4QlYsSUFBOUIsRUFBb0M7QUFDbEMsU0FBT0EsS0FBS0wsSUFBTCxLQUFjLDBCQUFkLElBQTRDSyxLQUFLVyxXQUFMLENBQWlCaEIsSUFBakIsS0FBMEIsa0JBQTdFO0FBQ0Q7O0FBRUQsU0FBU2lCLGlCQUFULENBQTJCWixJQUEzQixFQUFpQzs7QUFFL0IsU0FBT0EsS0FBS0wsSUFBTCxLQUFjLHdCQUFkLElBQTBDSyxLQUFLVyxXQUEvQyxJQUE4RFgsS0FBS1csV0FBTCxDQUFpQmhCLElBQWpCLEtBQTBCLGtCQUEvRjtBQUNEOztBQUVEa0IsT0FBT0MsT0FBUCxHQUFpQjtBQUNmQyxRQUFNO0FBQ0pwQixVQUFNLFFBREY7QUFFSnFCLFVBQU07QUFDSkMsZ0JBQVUsYUFETjtBQUVKQyxtQkFBYSw0Q0FGVDtBQUdKQyxXQUFLLDBCQUFRLHNCQUFSLENBSEQsRUFGRjs7QUFPSkMsYUFBUyxZQVBMO0FBUUpDLFlBQVE7QUFDTjtBQUNFMUIsWUFBTSxRQURSO0FBRUUyQixrQkFBWTtBQUNWQyxlQUFPO0FBQ0w1QixnQkFBTSxTQUREO0FBRUw2QixtQkFBUyxDQUZKLEVBREc7O0FBS1ZDLG9CQUFZLEVBQUU5QixNQUFNLFNBQVIsRUFMRjtBQU1WK0IsMEJBQWtCLEVBQUUvQixNQUFNLFNBQVIsRUFOUixFQUZkOztBQVVFZ0MsNEJBQXNCLEtBVnhCLEVBRE0sQ0FSSixFQURTOzs7O0FBd0JmQyxRQXhCZSwrQkF3QlJDLE9BeEJRLEVBd0JDO0FBQ2QsVUFBSUMsUUFBUSxDQUFaO0FBQ0EsVUFBTUMsZUFBZSxFQUFyQjtBQUNBLFVBQU1DO0FBQ0pULGVBQU8sQ0FESDtBQUVKRSxvQkFBWSxLQUZSO0FBR0pDLDBCQUFrQixLQUhkO0FBSURHLGNBQVFHLE9BQVIsQ0FBZ0IsQ0FBaEIsQ0FKQyxDQUFOOzs7QUFPQSxlQUFTQyxlQUFULEN
|