diff options
Diffstat (limited to 'tools/eslint/lib/rules/curly.js')
-rw-r--r-- | tools/eslint/lib/rules/curly.js | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/tools/eslint/lib/rules/curly.js b/tools/eslint/lib/rules/curly.js new file mode 100644 index 0000000000..2bfcfb2798 --- /dev/null +++ b/tools/eslint/lib/rules/curly.js @@ -0,0 +1,103 @@ +/** + * @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"); + } + }; + +}; |