/**
							 | 
						|
								 * @fileoverview Rule to flag when IIFE is not wrapped in parens
							 | 
						|
								 * @author Ilya Volodin
							 | 
						|
								 * @deprecated in ESLint v8.53.0
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								"use strict";
							 | 
						|
								
							 | 
						|
								//------------------------------------------------------------------------------
							 | 
						|
								// Requirements
							 | 
						|
								//------------------------------------------------------------------------------
							 | 
						|
								
							 | 
						|
								const astUtils = require("./utils/ast-utils");
							 | 
						|
								const eslintUtils = require("@eslint-community/eslint-utils");
							 | 
						|
								
							 | 
						|
								//----------------------------------------------------------------------
							 | 
						|
								// Helpers
							 | 
						|
								//----------------------------------------------------------------------
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Check if the given node is callee of a `NewExpression` node
							 | 
						|
								 * @param {ASTNode} node node to check
							 | 
						|
								 * @returns {boolean} True if the node is callee of a `NewExpression` node
							 | 
						|
								 * @private
							 | 
						|
								 */
							 | 
						|
								function isCalleeOfNewExpression(node) {
							 | 
						|
								    const maybeCallee = node.parent.type === "ChainExpression"
							 | 
						|
								        ? node.parent
							 | 
						|
								        : node;
							 | 
						|
								
							 | 
						|
								    return (
							 | 
						|
								        maybeCallee.parent.type === "NewExpression" &&
							 | 
						|
								        maybeCallee.parent.callee === maybeCallee
							 | 
						|
								    );
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								//------------------------------------------------------------------------------
							 | 
						|
								// Rule Definition
							 | 
						|
								//------------------------------------------------------------------------------
							 | 
						|
								
							 | 
						|
								/** @type {import('../shared/types').Rule} */
							 | 
						|
								module.exports = {
							 | 
						|
								    meta: {
							 | 
						|
								        deprecated: true,
							 | 
						|
								        replacedBy: [],
							 | 
						|
								        type: "layout",
							 | 
						|
								
							 | 
						|
								        docs: {
							 | 
						|
								            description: "Require parentheses around immediate `function` invocations",
							 | 
						|
								            recommended: false,
							 | 
						|
								            url: "https://eslint.org/docs/latest/rules/wrap-iife"
							 | 
						|
								        },
							 | 
						|
								
							 | 
						|
								        schema: [
							 | 
						|
								            {
							 | 
						|
								                enum: ["outside", "inside", "any"]
							 | 
						|
								            },
							 | 
						|
								            {
							 | 
						|
								                type: "object",
							 | 
						|
								                properties: {
							 | 
						|
								                    functionPrototypeMethods: {
							 | 
						|
								                        type: "boolean",
							 | 
						|
								                        default: false
							 | 
						|
								                    }
							 | 
						|
								                },
							 | 
						|
								                additionalProperties: false
							 | 
						|
								            }
							 | 
						|
								        ],
							 | 
						|
								
							 | 
						|
								        fixable: "code",
							 | 
						|
								        messages: {
							 | 
						|
								            wrapInvocation: "Wrap an immediate function invocation in parentheses.",
							 | 
						|
								            wrapExpression: "Wrap only the function expression in parens.",
							 | 
						|
								            moveInvocation: "Move the invocation into the parens that contain the function."
							 | 
						|
								        }
							 | 
						|
								    },
							 | 
						|
								
							 | 
						|
								    create(context) {
							 | 
						|
								
							 | 
						|
								        const style = context.options[0] || "outside";
							 | 
						|
								        const includeFunctionPrototypeMethods = context.options[1] && context.options[1].functionPrototypeMethods;
							 | 
						|
								
							 | 
						|
								        const sourceCode = context.sourceCode;
							 | 
						|
								
							 | 
						|
								        /**
							 | 
						|
								         * Check if the node is wrapped in any (). All parens count: grouping parens and parens for constructs such as if()
							 | 
						|
								         * @param {ASTNode} node node to evaluate
							 | 
						|
								         * @returns {boolean} True if it is wrapped in any parens
							 | 
						|
								         * @private
							 | 
						|
								         */
							 | 
						|
								        function isWrappedInAnyParens(node) {
							 | 
						|
								            return astUtils.isParenthesised(sourceCode, node);
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        /**
							 | 
						|
								         * Check if the node is wrapped in grouping (). Parens for constructs such as if() don't count
							 | 
						|
								         * @param {ASTNode} node node to evaluate
							 | 
						|
								         * @returns {boolean} True if it is wrapped in grouping parens
							 | 
						|
								         * @private
							 | 
						|
								         */
							 | 
						|
								        function isWrappedInGroupingParens(node) {
							 | 
						|
								            return eslintUtils.isParenthesized(1, node, sourceCode);
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        /**
							 | 
						|
								         * Get the function node from an IIFE
							 | 
						|
								         * @param {ASTNode} node node to evaluate
							 | 
						|
								         * @returns {ASTNode} node that is the function expression of the given IIFE, or null if none exist
							 | 
						|
								         */
							 | 
						|
								        function getFunctionNodeFromIIFE(node) {
							 | 
						|
								            const callee = astUtils.skipChainExpression(node.callee);
							 | 
						|
								
							 | 
						|
								            if (callee.type === "FunctionExpression") {
							 | 
						|
								                return callee;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            if (includeFunctionPrototypeMethods &&
							 | 
						|
								                callee.type === "MemberExpression" &&
							 | 
						|
								                callee.object.type === "FunctionExpression" &&
							 | 
						|
								                (astUtils.getStaticPropertyName(callee) === "call" || astUtils.getStaticPropertyName(callee) === "apply")
							 | 
						|
								            ) {
							 | 
						|
								                return callee.object;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            return null;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								        return {
							 | 
						|
								            CallExpression(node) {
							 | 
						|
								                const innerNode = getFunctionNodeFromIIFE(node);
							 | 
						|
								
							 | 
						|
								                if (!innerNode) {
							 | 
						|
								                    return;
							 | 
						|
								                }
							 | 
						|
								
							 | 
						|
								                const isCallExpressionWrapped = isWrappedInAnyParens(node),
							 | 
						|
								                    isFunctionExpressionWrapped = isWrappedInAnyParens(innerNode);
							 | 
						|
								
							 | 
						|
								                if (!isCallExpressionWrapped && !isFunctionExpressionWrapped) {
							 | 
						|
								                    context.report({
							 | 
						|
								                        node,
							 | 
						|
								                        messageId: "wrapInvocation",
							 | 
						|
								                        fix(fixer) {
							 | 
						|
								                            const nodeToSurround = style === "inside" ? innerNode : node;
							 | 
						|
								
							 | 
						|
								                            return fixer.replaceText(nodeToSurround, `(${sourceCode.getText(nodeToSurround)})`);
							 | 
						|
								                        }
							 | 
						|
								                    });
							 | 
						|
								                } else if (style === "inside" && !isFunctionExpressionWrapped) {
							 | 
						|
								                    context.report({
							 | 
						|
								                        node,
							 | 
						|
								                        messageId: "wrapExpression",
							 | 
						|
								                        fix(fixer) {
							 | 
						|
								
							 | 
						|
								                            // The outer call expression will always be wrapped at this point.
							 | 
						|
								
							 | 
						|
								                            if (isWrappedInGroupingParens(node) && !isCalleeOfNewExpression(node)) {
							 | 
						|
								
							 | 
						|
								                                /*
							 | 
						|
								                                 * Parenthesize the function expression and remove unnecessary grouping parens around the call expression.
							 | 
						|
								                                 * Replace the range between the end of the function expression and the end of the call expression.
							 | 
						|
								                                 * for example, in `(function(foo) {}(bar))`, the range `(bar))` should get replaced with `)(bar)`.
							 | 
						|
								                                 */
							 | 
						|
								
							 | 
						|
								                                const parenAfter = sourceCode.getTokenAfter(node);
							 | 
						|
								
							 | 
						|
								                                return fixer.replaceTextRange(
							 | 
						|
								                                    [innerNode.range[1], parenAfter.range[1]],
							 | 
						|
								                                    `)${sourceCode.getText().slice(innerNode.range[1], parenAfter.range[0])}`
							 | 
						|
								                                );
							 | 
						|
								                            }
							 | 
						|
								
							 | 
						|
								                            /*
							 | 
						|
								                             * Call expression is wrapped in mandatory parens such as if(), or in necessary grouping parens.
							 | 
						|
								                             * These parens cannot be removed, so just parenthesize the function expression.
							 | 
						|
								                             */
							 | 
						|
								
							 | 
						|
								                            return fixer.replaceText(innerNode, `(${sourceCode.getText(innerNode)})`);
							 | 
						|
								                        }
							 | 
						|
								                    });
							 | 
						|
								                } else if (style === "outside" && !isCallExpressionWrapped) {
							 | 
						|
								                    context.report({
							 | 
						|
								                        node,
							 | 
						|
								                        messageId: "moveInvocation",
							 | 
						|
								                        fix(fixer) {
							 | 
						|
								
							 | 
						|
								                            /*
							 | 
						|
								                             * The inner function expression will always be wrapped at this point.
							 | 
						|
								                             * It's only necessary to replace the range between the end of the function expression
							 | 
						|
								                             * and the call expression. For example, in `(function(foo) {})(bar)`, the range `)(bar)`
							 | 
						|
								                             * should get replaced with `(bar))`.
							 | 
						|
								                             */
							 | 
						|
								                            const parenAfter = sourceCode.getTokenAfter(innerNode);
							 | 
						|
								
							 | 
						|
								                            return fixer.replaceTextRange(
							 | 
						|
								                                [parenAfter.range[0], node.range[1]],
							 | 
						|
								                                `${sourceCode.getText().slice(parenAfter.range[1], node.range[1])})`
							 | 
						|
								                            );
							 | 
						|
								                        }
							 | 
						|
								                    });
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								        };
							 | 
						|
								
							 | 
						|
								    }
							 | 
						|
								};
							 |