1/** 2 * @fileoverview Rule to enforce a particular function style 3 * @author Nicholas C. Zakas 4 */ 5"use strict"; 6 7//------------------------------------------------------------------------------ 8// Rule Definition 9//------------------------------------------------------------------------------ 10 11module.exports = { 12 meta: { 13 type: "suggestion", 14 15 docs: { 16 description: "enforce the consistent use of either `function` declarations or expressions", 17 category: "Stylistic Issues", 18 recommended: false, 19 url: "https://eslint.org/docs/rules/func-style" 20 }, 21 22 schema: [ 23 { 24 enum: ["declaration", "expression"] 25 }, 26 { 27 type: "object", 28 properties: { 29 allowArrowFunctions: { 30 type: "boolean", 31 default: false 32 } 33 }, 34 additionalProperties: false 35 } 36 ], 37 38 messages: { 39 expression: "Expected a function expression.", 40 declaration: "Expected a function declaration." 41 } 42 }, 43 44 create(context) { 45 46 const style = context.options[0], 47 allowArrowFunctions = context.options[1] && context.options[1].allowArrowFunctions, 48 enforceDeclarations = (style === "declaration"), 49 stack = []; 50 51 const nodesToCheck = { 52 FunctionDeclaration(node) { 53 stack.push(false); 54 55 if (!enforceDeclarations && node.parent.type !== "ExportDefaultDeclaration") { 56 context.report({ node, messageId: "expression" }); 57 } 58 }, 59 "FunctionDeclaration:exit"() { 60 stack.pop(); 61 }, 62 63 FunctionExpression(node) { 64 stack.push(false); 65 66 if (enforceDeclarations && node.parent.type === "VariableDeclarator") { 67 context.report({ node: node.parent, messageId: "declaration" }); 68 } 69 }, 70 "FunctionExpression:exit"() { 71 stack.pop(); 72 }, 73 74 ThisExpression() { 75 if (stack.length > 0) { 76 stack[stack.length - 1] = true; 77 } 78 } 79 }; 80 81 if (!allowArrowFunctions) { 82 nodesToCheck.ArrowFunctionExpression = function() { 83 stack.push(false); 84 }; 85 86 nodesToCheck["ArrowFunctionExpression:exit"] = function(node) { 87 const hasThisExpr = stack.pop(); 88 89 if (enforceDeclarations && !hasThisExpr && node.parent.type === "VariableDeclarator") { 90 context.report({ node: node.parent, messageId: "declaration" }); 91 } 92 }; 93 } 94 95 return nodesToCheck; 96 97 } 98}; 99