Repository: eslint/eslint
File: lib/rules/no-extra-parens.js (JavaScript)

Code before:
            const maybeCallNode = astUtils.skipChainExpression(node);

            return maybeCallNode.type === "CallExpression" && maybeCallNode.callee.type === "FunctionExpression";
        }

        /**
         * Determines if the given node can be the assignment target in destructuring or the LHS of an assignment.
         * This is to avoid an autofix that could change behavior because parsers mistakenly allow invalid syntax,
         * such as `(a = b) = c` and `[(a = b) = c] = []`. Ideally, this function shouldn't be necessary.
         * @param {ASTNode} [node] The node to check
         * @returns {boolean} `true` if the given node can be a valid assignment target
         */
        function canBeAssignmentTarget(node) {
            return node && (node.type === "Identifier" || node.type === "MemberExpression");
        }

        /**
         * Checks if a node is fixable.
         * A node is fixable if removing a single pair of surrounding parentheses does not turn it
         * into a directive.
         * @param {ASTNode} node The node to evaluate.
         * @returns {boolean} Whether or not the node is fixable.
         * @private
         */
        function isFixable(node) {
            if (!(node.type === "Literal" && typeof node.value === "string")) {
                return true;
            }
            if (isParenthesisedTwice(node)) {
                return true;
            }
            return !astUtils.isExpressionInOrJustAfterDirectivePrologue(sourceCode, node.parent);
        }

        /**
         * Report the node
         * @param {ASTNode} node node to evaluate
         * @returns {void}
         * @private
         */
        function report(node) {
            const leftParenToken = sourceCode.getTokenBefore(node);
            const rightParenToken = sourceCode.getTokenAfter(node);

            if (!isParenthesisedTwice(node)) {
                if (tokensToIgnore.has(sourceCode.getFirstToken(node))) {
                    return;
                }

                if (isIIFE(node) && !isParenthesised(node.callee)) {
                    return;

Review comment (refactor):
Can we refactor this a bit to make it easier to understand? And maybe add a comment?

```suggestion
            // if it's not a string literal it can be autofixed
            if (node.type !== "Literal" || typeof node.value !== "string") {
```

Code after:
            const maybeCallNode = astUtils.skipChainExpression(node);

            return maybeCallNode.type === "CallExpression" && maybeCallNode.callee.type === "FunctionExpression";
        }

        /**
         * Determines if the given node can be the assignment target in destructuring or the LHS of an assignment.
         * This is to avoid an autofix that could change behavior because parsers mistakenly allow invalid syntax,
         * such as `(a = b) = c` and `[(a = b) = c] = []`. Ideally, this function shouldn't be necessary.
         * @param {ASTNode} [node] The node to check
         * @returns {boolean} `true` if the given node can be a valid assignment target
         */
        function canBeAssignmentTarget(node) {
            return node && (node.type === "Identifier" || node.type === "MemberExpression");
        }

        /**
         * Checks if a node is fixable.
         * A node is fixable if removing a single pair of surrounding parentheses does not turn it
         * into a directive after fixing other nodes.
         * Almost all nodes are fixable, except if all of the following conditions are met:
         * The node is a string Literal
         * It has a single pair of parentheses
         * It is the only child of an ExpressionStatement
         * @param {ASTNode} node The node to evaluate.
         * @returns {boolean} Whether or not the node is fixable.
         * @private
         */
        function isFixable(node) {

            // if it's not a string literal it can be autofixed
            if (node.type !== "Literal" || typeof node.value !== "string") {
                return true;
            }
            if (isParenthesisedTwice(node)) {
                return true;
            }
            return !astUtils.isTopLevelExpressionStatement(node.parent);
        }

        /**
         * Report the node
         * @param {ASTNode} node node to evaluate
         * @returns {void}
         * @private
         */
        function report(node) {
            const leftParenToken = sourceCode.getTokenBefore(node);
            const rightParenToken = sourceCode.getTokenAfter(node);

            if (!isParenthesisedTwice(node)) {