|                                                                                                                                        |  | /** * @fileoverview Rule to flag blocks with no reason to exist * @author Brandon Mills */
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */module.exports = {    meta: {        type: "suggestion",
        docs: {            description: "Disallow unnecessary nested blocks",            recommended: false,            url: "https://eslint.org/docs/latest/rules/no-lone-blocks"        },
        schema: [],
        messages: {            redundantBlock: "Block is redundant.",            redundantNestedBlock: "Nested block is redundant."        }    },
    create(context) {
        // A stack of lone blocks to be checked for block-level bindings
        const loneBlocks = [];        let ruleDef;        const sourceCode = context.sourceCode;
        /**         * Reports a node as invalid.         * @param {ASTNode} node The node to be reported.         * @returns {void}         */        function report(node) {            const messageId = node.parent.type === "BlockStatement" || node.parent.type === "StaticBlock"                ? "redundantNestedBlock"                : "redundantBlock";
            context.report({                node,                messageId            });        }
        /**         * Checks for any occurrence of a BlockStatement in a place where lists of statements can appear         * @param {ASTNode} node The node to check         * @returns {boolean} True if the node is a lone block.         */        function isLoneBlock(node) {            return node.parent.type === "BlockStatement" ||                node.parent.type === "StaticBlock" ||                node.parent.type === "Program" ||
                // Don't report blocks in switch cases if the block is the only statement of the case.
                node.parent.type === "SwitchCase" && !(node.parent.consequent[0] === node && node.parent.consequent.length === 1);        }
        /**         * Checks the enclosing block of the current node for block-level bindings,         * and "marks it" as valid if any.         * @param {ASTNode} node The current node to check.         * @returns {void}         */        function markLoneBlock(node) {            if (loneBlocks.length === 0) {                return;            }
            const block = node.parent;
            if (loneBlocks[loneBlocks.length - 1] === block) {                loneBlocks.pop();            }        }
        // Default rule definition: report all lone blocks
        ruleDef = {            BlockStatement(node) {                if (isLoneBlock(node)) {                    report(node);                }            }        };
        // ES6: report blocks without block-level bindings, or that's only child of another block
        if (context.languageOptions.ecmaVersion >= 2015) {            ruleDef = {                BlockStatement(node) {                    if (isLoneBlock(node)) {                        loneBlocks.push(node);                    }                },                "BlockStatement:exit"(node) {                    if (loneBlocks.length > 0 && loneBlocks[loneBlocks.length - 1] === node) {                        loneBlocks.pop();                        report(node);                    } else if (                        (                            node.parent.type === "BlockStatement" ||                            node.parent.type === "StaticBlock"                        ) &&                        node.parent.body.length === 1                    ) {                        report(node);                    }                }            };
            ruleDef.VariableDeclaration = function(node) {                if (node.kind === "let" || node.kind === "const") {                    markLoneBlock(node);                }            };
            ruleDef.FunctionDeclaration = function(node) {                if (sourceCode.getScope(node).isStrict) {                    markLoneBlock(node);                }            };
            ruleDef.ClassDeclaration = markLoneBlock;        }
        return ruleDef;    }};
 |