mirror of https://github.com/lukechilds/node.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
3.4 KiB
113 lines
3.4 KiB
/**
|
|
* @fileoverview Rule to ensure newline per method call when chaining calls
|
|
* @author Rajendra Patil
|
|
* @copyright 2016 Rajendra Patil. All rights reserved.
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Rule Definition
|
|
//------------------------------------------------------------------------------
|
|
|
|
module.exports = function(context) {
|
|
|
|
var options = context.options[0] || {},
|
|
codeStateMap = {},
|
|
ignoreChainWithDepth = options.ignoreChainWithDepth || 2;
|
|
|
|
/**
|
|
* Check and Capture State if the chained calls/members
|
|
* @param {ASTNode} node The node to check
|
|
* @param {object} codeState The state of the code current code to be filled
|
|
* @returns {void}
|
|
*/
|
|
function checkAndCaptureStateRecursively(node, codeState) {
|
|
var valid = false,
|
|
objectLineNumber,
|
|
propertyLineNumber;
|
|
if (node.callee) {
|
|
node = node.callee;
|
|
codeState.hasFunctionCall = true;
|
|
}
|
|
|
|
if (node.object) {
|
|
codeState.depth++;
|
|
|
|
objectLineNumber = node.object.loc.end.line;
|
|
propertyLineNumber = node.property.loc.end.line;
|
|
valid = node.computed || propertyLineNumber > objectLineNumber;
|
|
|
|
if (!valid) {
|
|
codeState.reports.push({
|
|
node: node,
|
|
text: "Expected line break after `{{code}}`.",
|
|
depth: codeState.depth
|
|
});
|
|
}
|
|
// Recurse
|
|
checkAndCaptureStateRecursively(node.object, codeState);
|
|
}
|
|
|
|
}
|
|
/**
|
|
* Verify and report the captured state report
|
|
* @param {object} codeState contains the captured state with `hasFunctionCall, reports and depth`
|
|
* @returns {void}
|
|
*/
|
|
function reportState(codeState) {
|
|
var report;
|
|
if (codeState.hasFunctionCall && codeState.depth > ignoreChainWithDepth && codeState.reports) {
|
|
while (codeState.reports.length) {
|
|
report = codeState.reports.shift();
|
|
context.report(report.node, report.text, {
|
|
code: context.getSourceCode().getText(report.node.object).replace(/\r\n|\r|\n/g, "\\n") // Not to print newlines in error report
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize the node state object with default values.
|
|
* @returns {void}
|
|
*/
|
|
function initializeState() {
|
|
return {
|
|
visited: false,
|
|
hasFunctionCall: false,
|
|
depth: 1,
|
|
reports: []
|
|
};
|
|
}
|
|
/**
|
|
* Process the said node and recurse internally
|
|
* @param {ASTNode} node The node to check
|
|
* @returns {void}
|
|
*/
|
|
function processNode(node) {
|
|
var stateKey = [node.loc.start.line, node.loc.start.column].join("@"),
|
|
codeState = codeStateMap[stateKey] = (codeStateMap[stateKey] || initializeState());
|
|
if (!codeState.visited) {
|
|
codeState.visited = true;
|
|
checkAndCaptureStateRecursively(node, codeState);
|
|
}
|
|
reportState(codeState);
|
|
}
|
|
|
|
return {
|
|
"CallExpression": processNode,
|
|
"MemberExpression": processNode
|
|
};
|
|
};
|
|
|
|
module.exports.schema = [{
|
|
"type": "object",
|
|
"properties": {
|
|
"ignoreChainWithDepth": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"maximum": 10
|
|
}
|
|
},
|
|
"additionalProperties": false
|
|
}];
|
|
|