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.
		
		
		
		
			
				
					176 lines
				
				5.4 KiB
			
		
		
			
		
	
	
					176 lines
				
				5.4 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @fileoverview A rule to set the maximum number of statements in a function.
							 | 
						||
| 
								 | 
							
								 * @author Ian Christian Myers
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								"use strict";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//------------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								// Requirements
							 | 
						||
| 
								 | 
							
								//------------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const lodash = require("lodash");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const astUtils = require("./utils/ast-utils");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//------------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								// Rule Definition
							 | 
						||
| 
								 | 
							
								//------------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = {
							 | 
						||
| 
								 | 
							
								    meta: {
							 | 
						||
| 
								 | 
							
								        type: "suggestion",
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        docs: {
							 | 
						||
| 
								 | 
							
								            description: "enforce a maximum number of statements allowed in function blocks",
							 | 
						||
| 
								 | 
							
								            category: "Stylistic Issues",
							 | 
						||
| 
								 | 
							
								            recommended: false,
							 | 
						||
| 
								 | 
							
								            url: "https://eslint.org/docs/rules/max-statements"
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        schema: [
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                oneOf: [
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        type: "integer",
							 | 
						||
| 
								 | 
							
								                        minimum: 0
							 | 
						||
| 
								 | 
							
								                    },
							 | 
						||
| 
								 | 
							
								                    {
							 | 
						||
| 
								 | 
							
								                        type: "object",
							 | 
						||
| 
								 | 
							
								                        properties: {
							 | 
						||
| 
								 | 
							
								                            maximum: {
							 | 
						||
| 
								 | 
							
								                                type: "integer",
							 | 
						||
| 
								 | 
							
								                                minimum: 0
							 | 
						||
| 
								 | 
							
								                            },
							 | 
						||
| 
								 | 
							
								                            max: {
							 | 
						||
| 
								 | 
							
								                                type: "integer",
							 | 
						||
| 
								 | 
							
								                                minimum: 0
							 | 
						||
| 
								 | 
							
								                            }
							 | 
						||
| 
								 | 
							
								                        },
							 | 
						||
| 
								 | 
							
								                        additionalProperties: false
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                ]
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                type: "object",
							 | 
						||
| 
								 | 
							
								                properties: {
							 | 
						||
| 
								 | 
							
								                    ignoreTopLevelFunctions: {
							 | 
						||
| 
								 | 
							
								                        type: "boolean"
							 | 
						||
| 
								 | 
							
								                    }
							 | 
						||
| 
								 | 
							
								                },
							 | 
						||
| 
								 | 
							
								                additionalProperties: false
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        ],
							 | 
						||
| 
								 | 
							
								        messages: {
							 | 
						||
| 
								 | 
							
								            exceed: "{{name}} has too many statements ({{count}}). Maximum allowed is {{max}}."
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    create(context) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        //--------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								        // Helpers
							 | 
						||
| 
								 | 
							
								        //--------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const functionStack = [],
							 | 
						||
| 
								 | 
							
								            option = context.options[0],
							 | 
						||
| 
								 | 
							
								            ignoreTopLevelFunctions = context.options[1] && context.options[1].ignoreTopLevelFunctions || false,
							 | 
						||
| 
								 | 
							
								            topLevelFunctions = [];
							 | 
						||
| 
								 | 
							
								        let maxStatements = 10;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (
							 | 
						||
| 
								 | 
							
								            typeof option === "object" &&
							 | 
						||
| 
								 | 
							
								            (Object.prototype.hasOwnProperty.call(option, "maximum") || Object.prototype.hasOwnProperty.call(option, "max"))
							 | 
						||
| 
								 | 
							
								        ) {
							 | 
						||
| 
								 | 
							
								            maxStatements = option.maximum || option.max;
							 | 
						||
| 
								 | 
							
								        } else if (typeof option === "number") {
							 | 
						||
| 
								 | 
							
								            maxStatements = option;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /**
							 | 
						||
| 
								 | 
							
								         * Reports a node if it has too many statements
							 | 
						||
| 
								 | 
							
								         * @param {ASTNode} node node to evaluate
							 | 
						||
| 
								 | 
							
								         * @param {int} count Number of statements in node
							 | 
						||
| 
								 | 
							
								         * @param {int} max Maximum number of statements allowed
							 | 
						||
| 
								 | 
							
								         * @returns {void}
							 | 
						||
| 
								 | 
							
								         * @private
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        function reportIfTooManyStatements(node, count, max) {
							 | 
						||
| 
								 | 
							
								            if (count > max) {
							 | 
						||
| 
								 | 
							
								                const name = lodash.upperFirst(astUtils.getFunctionNameWithKind(node));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                context.report({
							 | 
						||
| 
								 | 
							
								                    node,
							 | 
						||
| 
								 | 
							
								                    messageId: "exceed",
							 | 
						||
| 
								 | 
							
								                    data: { name, count, max }
							 | 
						||
| 
								 | 
							
								                });
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /**
							 | 
						||
| 
								 | 
							
								         * When parsing a new function, store it in our function stack
							 | 
						||
| 
								 | 
							
								         * @returns {void}
							 | 
						||
| 
								 | 
							
								         * @private
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        function startFunction() {
							 | 
						||
| 
								 | 
							
								            functionStack.push(0);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /**
							 | 
						||
| 
								 | 
							
								         * Evaluate the node at the end of function
							 | 
						||
| 
								 | 
							
								         * @param {ASTNode} node node to evaluate
							 | 
						||
| 
								 | 
							
								         * @returns {void}
							 | 
						||
| 
								 | 
							
								         * @private
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        function endFunction(node) {
							 | 
						||
| 
								 | 
							
								            const count = functionStack.pop();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (ignoreTopLevelFunctions && functionStack.length === 0) {
							 | 
						||
| 
								 | 
							
								                topLevelFunctions.push({ node, count });
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                reportIfTooManyStatements(node, count, maxStatements);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /**
							 | 
						||
| 
								 | 
							
								         * Increment the count of the functions
							 | 
						||
| 
								 | 
							
								         * @param {ASTNode} node node to evaluate
							 | 
						||
| 
								 | 
							
								         * @returns {void}
							 | 
						||
| 
								 | 
							
								         * @private
							 | 
						||
| 
								 | 
							
								         */
							 | 
						||
| 
								 | 
							
								        function countStatements(node) {
							 | 
						||
| 
								 | 
							
								            functionStack[functionStack.length - 1] += node.body.length;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        //--------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								        // Public API
							 | 
						||
| 
								 | 
							
								        //--------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return {
							 | 
						||
| 
								 | 
							
								            FunctionDeclaration: startFunction,
							 | 
						||
| 
								 | 
							
								            FunctionExpression: startFunction,
							 | 
						||
| 
								 | 
							
								            ArrowFunctionExpression: startFunction,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            BlockStatement: countStatements,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            "FunctionDeclaration:exit": endFunction,
							 | 
						||
| 
								 | 
							
								            "FunctionExpression:exit": endFunction,
							 | 
						||
| 
								 | 
							
								            "ArrowFunctionExpression:exit": endFunction,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            "Program:exit"() {
							 | 
						||
| 
								 | 
							
								                if (topLevelFunctions.length === 1) {
							 | 
						||
| 
								 | 
							
								                    return;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                topLevelFunctions.forEach(element => {
							 | 
						||
| 
								 | 
							
								                    const count = element.count;
							 | 
						||
| 
								 | 
							
								                    const node = element.node;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                    reportIfTooManyStatements(node, count, maxStatements);
							 | 
						||
| 
								 | 
							
								                });
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								};
							 |