/** * @fileoverview Rule to enforce a particular function style * @author Nicholas C. Zakas * @copyright 2013 Nicholas C. Zakas. All rights reserved. */ "use strict"; //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ module.exports = function(context) { var style = context.options[0], allowArrowFunctions = context.options[1] && context.options[1].allowArrowFunctions === true, enforceDeclarations = (style === "declaration"), stack = []; var nodesToCheck = { "Program": function() { stack = []; }, "FunctionDeclaration": function(node) { stack.push(false); if (!enforceDeclarations && node.parent.type !== "ExportDefaultDeclaration") { context.report(node, "Expected a function expression."); } }, "FunctionDeclaration:exit": function() { stack.pop(); }, "FunctionExpression": function(node) { stack.push(false); if (enforceDeclarations && node.parent.type === "VariableDeclarator") { context.report(node.parent, "Expected a function declaration."); } }, "FunctionExpression:exit": function() { stack.pop(); }, "ThisExpression": function() { if (stack.length > 0) { stack[stack.length - 1] = true; } } }; if (!allowArrowFunctions) { nodesToCheck.ArrowFunctionExpression = function() { stack.push(false); }; nodesToCheck["ArrowFunctionExpression:exit"] = function(node) { var hasThisExpr = stack.pop(); if (enforceDeclarations && !hasThisExpr && node.parent.type === "VariableDeclarator") { context.report(node.parent, "Expected a function declaration."); } }; } return nodesToCheck; }; module.exports.schema = [ { "enum": ["declaration", "expression"] }, { "type": "object", "properties": { "allowArrowFunctions": { "type": "boolean" } }, "additionalProperties": false } ];