128 lines
3.6 KiB
Plaintext
128 lines
3.6 KiB
Plaintext
'use strict';
|
|
|
|
var utils = require('../utils.js');
|
|
require('eslint-visitor-keys');
|
|
require('espree');
|
|
require('estraverse');
|
|
|
|
const listeningNodes = [
|
|
"BreakStatement",
|
|
"ClassDeclaration",
|
|
"ContinueStatement",
|
|
"DebuggerStatement",
|
|
"DoWhileStatement",
|
|
"ExpressionStatement",
|
|
"ForInStatement",
|
|
"ForOfStatement",
|
|
"ForStatement",
|
|
"FunctionDeclaration",
|
|
"IfStatement",
|
|
"ImportDeclaration",
|
|
"LabeledStatement",
|
|
"ReturnStatement",
|
|
"SwitchStatement",
|
|
"ThrowStatement",
|
|
"TryStatement",
|
|
"VariableDeclaration",
|
|
"WhileStatement",
|
|
"WithStatement",
|
|
"ExportNamedDeclaration",
|
|
"ExportDefaultDeclaration",
|
|
"ExportAllDeclaration"
|
|
];
|
|
var maxStatementsPerLine = utils.createRule({
|
|
name: "max-statements-per-line",
|
|
package: "js",
|
|
meta: {
|
|
type: "layout",
|
|
docs: {
|
|
description: "Enforce a maximum number of statements allowed per line"
|
|
},
|
|
schema: [
|
|
{
|
|
type: "object",
|
|
properties: {
|
|
max: {
|
|
type: "integer",
|
|
minimum: 1,
|
|
default: 1
|
|
},
|
|
ignoredNodes: {
|
|
type: "array",
|
|
items: {
|
|
type: "string",
|
|
enum: listeningNodes
|
|
}
|
|
}
|
|
},
|
|
additionalProperties: false
|
|
}
|
|
],
|
|
messages: {
|
|
exceed: "This line has {{numberOfStatementsOnThisLine}} {{statements}}. Maximum allowed is {{maxStatementsPerLine}}."
|
|
}
|
|
},
|
|
create(context) {
|
|
const sourceCode = context.sourceCode;
|
|
const options = context.options[0] || {};
|
|
const maxStatementsPerLine = typeof options.max !== "undefined" ? options.max : 1;
|
|
const ignoredNodes = options.ignoredNodes || [];
|
|
let lastStatementLine = 0;
|
|
let numberOfStatementsOnThisLine = 0;
|
|
let firstExtraStatement = null;
|
|
const SINGLE_CHILD_ALLOWED = /^(?:(?:DoWhile|For|ForIn|ForOf|If|Labeled|While)Statement|Export(?:Default|Named)Declaration)$/u;
|
|
function reportFirstExtraStatementAndClear() {
|
|
if (firstExtraStatement) {
|
|
context.report({
|
|
node: firstExtraStatement,
|
|
messageId: "exceed",
|
|
data: {
|
|
numberOfStatementsOnThisLine,
|
|
maxStatementsPerLine,
|
|
statements: numberOfStatementsOnThisLine === 1 ? "statement" : "statements"
|
|
}
|
|
});
|
|
}
|
|
firstExtraStatement = null;
|
|
}
|
|
function getActualLastToken(node) {
|
|
return sourceCode.getLastToken(node, utils.isNotSemicolonToken);
|
|
}
|
|
function enterStatement(node) {
|
|
const line = node.loc.start.line;
|
|
if (node.parent && SINGLE_CHILD_ALLOWED.test(node.parent.type) && (!("alternate" in node.parent) || node.parent.alternate !== node)) {
|
|
return;
|
|
}
|
|
if (line === lastStatementLine) {
|
|
numberOfStatementsOnThisLine += 1;
|
|
} else {
|
|
reportFirstExtraStatementAndClear();
|
|
numberOfStatementsOnThisLine = 1;
|
|
lastStatementLine = line;
|
|
}
|
|
if (numberOfStatementsOnThisLine === maxStatementsPerLine + 1)
|
|
firstExtraStatement = firstExtraStatement || node;
|
|
}
|
|
function leaveStatement(node) {
|
|
const line = getActualLastToken(node).loc.end.line;
|
|
if (line !== lastStatementLine) {
|
|
reportFirstExtraStatementAndClear();
|
|
numberOfStatementsOnThisLine = 1;
|
|
lastStatementLine = line;
|
|
}
|
|
}
|
|
const listeners = {
|
|
"Program:exit": reportFirstExtraStatementAndClear
|
|
};
|
|
for (const node of listeningNodes) {
|
|
if (ignoredNodes.includes(node))
|
|
continue;
|
|
listeners[node] = enterStatement;
|
|
listeners[`${node}:exit`] = leaveStatement;
|
|
}
|
|
return listeners;
|
|
}
|
|
});
|
|
|
|
module.exports = maxStatementsPerLine;
|