|
|
|
/**
|
|
|
|
* @fileoverview Rule to flag statements without curly braces
|
|
|
|
* @author Nicholas C. Zakas
|
|
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Rule Definition
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
module.exports = function(context) {
|
|
|
|
|
|
|
|
var multiOnly = (context.options[0] === "multi");
|
|
|
|
var multiLine = (context.options[0] === "multi-line");
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
// Helpers
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determines if a given node is a one-liner that's on the same line as it's preceding code.
|
|
|
|
* @param {ASTNode} node The node to check.
|
|
|
|
* @returns {boolean} True if the node is a one-liner that's on the same line as it's preceding code.
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
function isCollapsedOneLiner(node) {
|
|
|
|
var before = context.getTokenBefore(node),
|
|
|
|
last = context.getLastToken(node);
|
|
|
|
return before.loc.start.line === last.loc.end.line;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks the body of a node to see if it's a block statement. Depending on
|
|
|
|
* the rule options, reports the appropriate problems.
|
|
|
|
* @param {ASTNode} node The node to report if there's a problem.
|
|
|
|
* @param {ASTNode} body The body node to check for blocks.
|
|
|
|
* @param {string} name The name to report if there's a problem.
|
|
|
|
* @param {string} suffix Additional string to add to the end of a report.
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
function checkBody(node, body, name, suffix) {
|
|
|
|
var hasBlock = (body.type === "BlockStatement");
|
|
|
|
|
|
|
|
if (multiOnly) {
|
|
|
|
if (hasBlock && body.body.length === 1) {
|
|
|
|
context.report(node, "Unnecessary { after '{{name}}'{{suffix}}.",
|
|
|
|
{
|
|
|
|
name: name,
|
|
|
|
suffix: (suffix ? " " + suffix : "")
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} else if (multiLine) {
|
|
|
|
if (!hasBlock && !isCollapsedOneLiner(body)) {
|
|
|
|
context.report(node, "Expected { after '{{name}}'{{suffix}}.",
|
|
|
|
{
|
|
|
|
name: name,
|
|
|
|
suffix: (suffix ? " " + suffix : "")
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!hasBlock) {
|
|
|
|
context.report(node, "Expected { after '{{name}}'{{suffix}}.",
|
|
|
|
{
|
|
|
|
name: name,
|
|
|
|
suffix: (suffix ? " " + suffix : "")
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
// Public
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
"IfStatement": function(node) {
|
|
|
|
|
|
|
|
checkBody(node, node.consequent, "if", "condition");
|
|
|
|
|
|
|
|
if (node.alternate && node.alternate.type !== "IfStatement") {
|
|
|
|
checkBody(node, node.alternate, "else");
|
|
|
|
}
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
"WhileStatement": function(node) {
|
|
|
|
checkBody(node, node.body, "while", "condition");
|
|
|
|
},
|
|
|
|
|
|
|
|
"DoWhileStatement": function (node) {
|
|
|
|
checkBody(node, node.body, "do");
|
|
|
|
},
|
|
|
|
|
|
|
|
"ForStatement": function(node) {
|
|
|
|
checkBody(node, node.body, "for", "condition");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports.schema = [
|
|
|
|
{
|
|
|
|
"enum": ["all", "multi", "multi-line"]
|
|
|
|
}
|
|
|
|
];
|