code:
/**
 * @fileoverview Disallow trailing spaces at the end of lines.
 * @author Nodeca Team <https://github.com/nodeca>
 * @deprecated in ESLint v8.53.0
 */
"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const astUtils = require("./utils/ast-utils");

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

/** @type {import('../shared/types').Rule} */
module.exports = {
    meta: {
        deprecated: true,
        replacedBy: [],
        type: "layout",

        docs: {
            description: "Disallow trailing whitespace at the end of lines",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-trailing-spaces"
        },

        fixable: "whitespace",

        schema: [
            {
                type: "object",
                properties: {
                    skipBlankLines: {
                        type: "boolean",
                        default: false
                    },
                    ignoreComments: {
                        type: "boolean",
                        default: false
                    }
                },
                additionalProperties: false
            }
        ],

        messages: {
            trailingSpace: "Trailing spaces not allowed."
        }
    },

    create(context) {
        const sourceCode = context.sourceCode;

        const BLANK_CLASS = "[ \t\u00a0\u2000-\u200b\u3000]",
            SKIP_BLANK = `^${BLANK_CLASS}*$`,
            NONBLANK = `${BLANK_CLASS}+$`;

        const options = context.options[0] || {},
            skipBlankLines = options.skipBlankLines || false,
            ignoreComments = options.ignoreComments || false;

        /**
         * Report the error message
         * @param {ASTNode} node node to report
         * @param {int[]} location range information
         * @param {int[]} fixRange Range based on the whole program
         * @returns {void}
         */
        function report(node, location, fixRange) {

            /*
             * Passing node is a bit dirty, because message data will contain big
             * text in `source`. But... who cares :) ?
             * One more kludge will not make worse the bloody wizardry of this
             * plugin.
             */
            context.report({
                node,
                loc: location,
                messageId: "trailingSpace",
                fix(fixer) {
                    return fixer.removeRange(fixRange);
                }
            });
        }

        /**
         * Given a list of comment nodes, return the line numbers for those comments.
         * @param {Array} comments An array of comment nodes.
         * @returns {number[]} An array of line numbers containing comments.
         */
        function getCommentLineNumbers(comments) {
            const lines = new Set();

            comments.forEach(comment => {
                const endLine = comment.type === "Block"
                    ? comment.loc.end.line - 1
                    : comment.loc.end.line;

                for (let i = comment.loc.start.line; i <= endLine; i++) {
                    lines.add(i);
                }
            });

            return lines;
        }

        //--------------------------------------------------------------------------
        // Public
        //--------------------------------------------------------------------------

        return {

            Program: function checkTrailingSpaces(node) {

                /*
                 * Let's hack. Since Espree does not return whitespace nodes,
                 * fetch the source code and do matching via regexps.
                 */

                const re = new RegExp(NONBLANK, "u"),
                    skipMatch = new RegExp(SKIP_BLANK, "u"),
                    lines = sourceCode.lines,
                    linebreaks = sourceCode.getText().match(astUtils.createGlobalLinebreakMatcher()),
                    comments = sourceCode.getAllComments(),
                    commentLineNumbers = getCommentLineNumbers(comments);

                let totalLength = 0,
                    fixRange = [];

                for (let i = 0, ii = lines.length; i < ii; i++) {
                    const lineNumber = i + 1;

                    /*
                     * Always add linebreak length to line length to accommodate for line break (\n or \r\n)
                     * Because during the fix time they also reserve one spot in the array.
                     * Usually linebreak length is 2 for \r\n (CRLF) and 1 for \n (LF)
                     */
                    const linebreakLength = linebreaks && linebreaks[i] ? linebreaks[i].length : 1;
                    const lineLength = lines[i].length + linebreakLength;

                    const matches = re.exec(lines[i]);

                    if (matches) {
                        const location = {
                            start: {
                                line: lineNumber,
                                column: matches.index
                            },
                            end: {
                                line: lineNumber,
                                column: lineLength - linebreakLength
                            }
                        };

                        const rangeStart = totalLength + location.start.column;
                        const rangeEnd = totalLength + location.end.column;
                        const containingNode = sourceCode.getNodeByRangeIndex(rangeStart);

                        if (containingNode && containingNode.type === "TemplateElement" &&
                          rangeStart > containingNode.parent.range[0] &&
                          rangeEnd < containingNode.parent.range[1]) {
                            totalLength += lineLength;
                            continue;
                        }

                        /*
                         * If the line has only whitespace, and skipBlankLines
                         * is true, don't report it
                         */
                        if (skipBlankLines && skipMatch.test(lines[i])) {
                            totalLength += lineLength;
                            continue;
                        }

                        fixRange = [rangeStart, rangeEnd];

                        if (!ignoreComments || !commentLineNumbers.has(lineNumber)) {
                            report(node, location, fixRange);
                        }
                    }

                    totalLength += lineLength;
                }
            }

        };
    }
};


code:
/**
 * @fileoverview Rule to flag when initializing to undefined
 * @author Ilya Volodin
 */

"use strict";

const astUtils = require("./utils/ast-utils");

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

/** @type {import('../shared/types').Rule} */
module.exports = {
    meta: {
        type: "suggestion",

        docs: {
            description: "Disallow initializing variables to `undefined`",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-undef-init"
        },

        schema: [],
        fixable: "code",

        messages: {
            unnecessaryUndefinedInit: "It's not necessary to initialize '{{name}}' to undefined."
        }
    },

    create(context) {

        const sourceCode = context.sourceCode;

        return {

            VariableDeclarator(node) {
                const name = sourceCode.getText(node.id),
                    init = node.init && node.init.name,
                    scope = sourceCode.getScope(node),
                    undefinedVar = astUtils.getVariableByName(scope, "undefined"),
                    shadowed = undefinedVar && undefinedVar.defs.length > 0,
                    lastToken = sourceCode.getLastToken(node);

                if (init === "undefined" && node.parent.kind !== "const" && !shadowed) {
                    context.report({
                        node,
                        messageId: "unnecessaryUndefinedInit",
                        data: { name },
                        fix(fixer) {
                            if (node.parent.kind === "var") {
                                return null;
                            }

                            if (node.id.type === "ArrayPattern" || node.id.type === "ObjectPattern") {

                                // Don't fix destructuring assignment to `undefined`.
                                return null;
                            }

                            if (sourceCode.commentsExistBetween(node.id, lastToken)) {
                                return null;
                            }

                            return fixer.removeRange([node.id.range[1], node.range[1]]);
                        }
                    });
                }
            }
        };

    }
};

license: mit


code:
/**
 * @fileoverview Rule to flag references to undeclared variables.
 * @author Mark Macdonald
 */
"use strict";

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

/**
 * Checks if the given node is the argument of a typeof operator.
 * @param {ASTNode} node The AST node being checked.
 * @returns {boolean} Whether or not the node is the argument of a typeof operator.
 */
function hasTypeOfOperator(node) {
    const parent = node.parent;

    return parent.type === "UnaryExpression" && parent.operator === "typeof";
}

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

/** @type {import('../shared/types').Rule} */
module.exports = {
    meta: {
        type: "problem",

        docs: {
            description: "Disallow the use of undeclared variables unless mentioned in `/*global */` comments",
            recommended: true,
            url: "https://eslint.org/docs/latest/rules/no-undef"
        },

        schema: [
            {
                type: "object",
                properties: {
                    typeof: {
                        type: "boolean",
                        default: false
                    }
                },
                additionalProperties: false
            }
        ],
        messages: {
            undef: "'{{name}}' is not defined."
        }
    },

    create(context) {
        const options = context.options[0];
        const considerTypeOf = options && options.typeof === true || false;
        const sourceCode = context.sourceCode;

        return {
            "Program:exit"(node) {
                const globalScope = sourceCode.getScope(node);

                globalScope.through.forEach(ref => {
                    const identifier = ref.identifier;

                    if (!considerTypeOf && hasTypeOfOperator(identifier)) {
                        return;
                    }

                    context.report({
                        node: identifier,
                        messageId: "undef",
                        data: identifier
                    });
                });
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to flag references to the undefined variable.
 * @author Michael Ficarra
 */
"use strict";

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

/** @type {import('../shared/types').Rule} */
module.exports = {
    meta: {
        type: "suggestion",

        docs: {
            description: "Disallow the use of `undefined` as an identifier",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-undefined"
        },

        schema: [],

        messages: {
            unexpectedUndefined: "Unexpected use of undefined."
        }
    },

    create(context) {

        const sourceCode = context.sourceCode;

        /**
         * Report an invalid "undefined" identifier node.
         * @param {ASTNode} node The node to report.
         * @returns {void}
         */
        function report(node) {
            context.report({
                node,
                messageId: "unexpectedUndefined"
            });
        }

        /**
         * Checks the given scope for references to `undefined` and reports
         * all references found.
         * @param {eslint-scope.Scope} scope The scope to check.
         * @returns {void}
         */
        function checkScope(scope) {
            const undefinedVar = scope.set.get("undefined");

            if (!undefinedVar) {
                return;
            }

            const references = undefinedVar.references;

            const defs = undefinedVar.defs;

            // Report non-initializing references (those are covered in defs below)
            references
                .filter(ref => !ref.init)
                .forEach(ref => report(ref.identifier));

            defs.forEach(def => report(def.name));
        }

        return {
            "Program:exit"(node) {
                const globalScope = sourceCode.getScope(node);

                const stack = [globalScope];

                while (stack.length) {
                    const scope = stack.pop();

                    stack.push(...scope.childScopes);
                    checkScope(scope);
                }
            }
        };

    }
};


code:
/**
 * @fileoverview Rule to flag dangling underscores in variable declarations.
 * @author Matt DuVall <http://www.mattduvall.com>
 */

"use strict";

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

/** @type {import('../shared/types').Rule} */
module.exports = {
    meta: {
        type: "suggestion",

        docs: {
            description: "Disallow dangling underscores in identifiers",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-underscore-dangle"
        },

        schema: [
            {
                type: "object",
                properties: {
                    allow: {
                        type: "array",
                        items: {
                            type: "string"
                        }
                    },
                    allowAfterThis: {
                        type: "boolean",
                        default: false
                    },
                    allowAfterSuper: {
                        type: "boolean",
                        default: false
                    },
                    allowAfterThisConstructor: {
                        type: "boolean",
                        default: false
                    },
                    enforceInMethodNames: {
                        type: "boolean",
                        default: false
                    },
                    allowFunctionParams: {
                        type: "boolean",
                        default: true
                    },
                    enforceInClassFields: {
                        type: "boolean",
                        default: false
                    },
                    allowInArrayDestructuring: {
                        type: "boolean",
                        default: true
                    },
                    allowInObjectDestructuring: {
                        type: "boolean",
                        default: true
                    }
                },
                additionalProperties: false
            }
        ],

        messages: {
            unexpectedUnderscore: "Unexpected dangling '_' in '{{identifier}}'."
        }
    },

    create(context) {

        const options = context.options[0] || {};
        const ALLOWED_VARIABLES = options.allow ? options.allow : [];
        const allowAfterThis = typeof options.allowAfterThis !== "undefined" ? options.allowAfterThis : false;
        const allowAfterSuper = typeof options.allowAfterSuper !== "undefined" ? options.allowAfterSuper : false;
        const allowAfterThisConstructor = typeof options.allowAfterThisConstructor !== "undefined" ? options.allowAfterThisConstructor : false;
        const enforceInMethodNames = typeof options.enforceInMethodNames !== "undefined" ? options.enforceInMethodNames : false;
        const enforceInClassFields = typeof options.enforceInClassFields !== "undefined" ? options.enforceInClassFields : false;
        const allowFunctionParams = typeof options.allowFunctionParams !== "undefined" ? options.allowFunctionParams : true;
        const allowInArrayDestructuring = typeof options.allowInArrayDestructuring !== "undefined" ? options.allowInArrayDestructuring : true;
        const allowInObjectDestructuring = typeof options.allowInObjectDestructuring !== "undefined" ? options.allowInObjectDestructuring : true;
        const sourceCode = context.sourceCode;

        //-------------------------------------------------------------------------
        // Helpers
        //-------------------------------------------------------------------------

        /**
         * Check if identifier is present inside the allowed option
         * @param {string} identifier name of the node
         * @returns {boolean} true if its is present
         * @private
         */
        function isAllowed(identifier) {
            return ALLOWED_VARIABLES.includes(identifier);
        }

        /**
         * Check if identifier has a dangling underscore
         * @param {string} identifier name of the node
         * @returns {boolean} true if its is present
         * @private
         */
        function hasDanglingUnderscore(identifier) {
            const len = identifier.length;

            return identifier !== "_" && (identifier[0] === "_" || identifier[len - 1] === "_");
        }

        /**
         * Check if identifier is a special case member expression
         * @param {string} identifier name of the node
         * @returns {boolean} true if its is a special case
         * @private
         */
        function isSpecialCaseIdentifierForMemberExpression(identifier) {
            return identifier === "__proto__";
        }

        /**
         * Check if identifier is a special case variable expression
         * @param {string} identifier name of the node
         * @returns {boolean} true if its is a special case
         * @private
         */
        function isSpecialCaseIdentifierInVariableExpression(identifier) {

            // Checks for the underscore library usage here
            return identifier === "_";
        }

        /**
         * Check if a node is a member reference of this.constructor
         * @param {ASTNode} node node to evaluate
         * @returns {boolean} true if it is a reference on this.constructor
         * @private
         */
        function isThisConstructorReference(node) {
            return node.object.type === "MemberExpression" &&
                node.object.property.name === "constructor" &&
                node.object.object.type === "ThisExpression";
        }

        /**
         * Check if function parameter has a dangling underscore.
         * @param {ASTNode} node function node to evaluate
         * @returns {void}
         * @private
         */
        function checkForDanglingUnderscoreInFunctionParameters(node) {
            if (!allowFunctionParams) {
                node.params.forEach(param => {
                    const { type } = param;
                    let nodeToCheck;

                    if (type === "RestElement") {
                        nodeToCheck = param.argument;
                    } else if (type === "AssignmentPattern") {
                        nodeToCheck = param.left;
                    } else {
                        nodeToCheck = param;
                    }

                    if (nodeToCheck.type === "Identifier") {
                        const identifier = nodeToCheck.name;

                        if (hasDanglingUnderscore(identifier) && !isAllowed(identifier)) {
                            context.report({
                                node: param,
                                messageId: "unexpectedUnderscore",
                                data: {
                                    identifier
                                }
                            });
                        }
                    }
                });
            }
        }

        /**
         * Check if function has a dangling underscore
         * @param {ASTNode} node node to evaluate
         * @returns {void}
         * @private
         */
        function checkForDanglingUnderscoreInFunction(node) {
            if (node.type === "FunctionDeclaration" && node.id) {
                const identifier = node.id.name;

                if (typeof identifier !== "undefined" && hasDanglingUnderscore(identifier) && !isAllowed(identifier)) {
                    context.report({
                        node,
                        messageId: "unexpectedUnderscore",
                        data: {
                            identifier
                        }
                    });
                }
            }
            checkForDanglingUnderscoreInFunctionParameters(node);
        }

        /**
         * Check if variable expression has a dangling underscore
         * @param {ASTNode} node node to evaluate
         * @returns {void}
         * @private
         */
        function checkForDanglingUnderscoreInVariableExpression(node) {
            sourceCode.getDeclaredVariables(node).forEach(variable => {
                const definition = variable.defs.find(def => def.node === node);
                const identifierNode = definition.name;
                const identifier = identifierNode.name;
                let parent = identifierNode.parent;

                while (!["VariableDeclarator", "ArrayPattern", "ObjectPattern"].includes(parent.type)) {
                    parent = parent.parent;
                }

                if (
                    hasDanglingUnderscore(identifier) &&
                    !isSpecialCaseIdentifierInVariableExpression(identifier) &&
                    !isAllowed(identifier) &&
                    !(allowInArrayDestructuring && parent.type === "ArrayPattern") &&
                    !(allowInObjectDestructuring && parent.type === "ObjectPattern")
                ) {
                    context.report({
                        node,
                        messageId: "unexpectedUnderscore",
                        data: {
                            identifier
                        }
                    });
                }
            });
        }

        /**
         * Check if member expression has a dangling underscore
         * @param {ASTNode} node node to evaluate
         * @returns {void}
         * @private
         */
        function checkForDanglingUnderscoreInMemberExpression(node) {
            const identifier = node.property.name,
                isMemberOfThis = node.object.type === "ThisExpression",
                isMemberOfSuper = node.object.type === "Super",
                isMemberOfThisConstructor = isThisConstructorReference(node);

            if (typeof identifier !== "undefined" && hasDanglingUnderscore(identifier) &&
                !(isMemberOfThis && allowAfterThis) &&
                !(isMemberOfSuper && allowAfterSuper) &&
                !(isMemberOfThisConstructor && allowAfterThisConstructor) &&
                !isSpecialCaseIdentifierForMemberExpression(identifier) && !isAllowed(identifier)) {
                context.report({
                    node,
                    messageId: "unexpectedUnderscore",
                    data: {
                        identifier
                    }
                });
            }
        }

        /**
         * Check if method declaration or method property has a dangling underscore
         * @param {ASTNode} node node to evaluate
         * @returns {void}
         * @private
         */
        function checkForDanglingUnderscoreInMethod(node) {
            const identifier = node.key.name;
            const isMethod = node.type === "MethodDefinition" || node.type === "Property" && node.method;

            if (typeof identifier !== "undefined" && enforceInMethodNames && isMethod && hasDanglingUnderscore(identifier) && !isAllowed(identifier)) {
                context.report({
                    node,
                    messageId: "unexpectedUnderscore",
                    data: {
                        identifier: node.key.type === "PrivateIdentifier"
                            ? `#${identifier}`
                            : identifier
                    }
                });
            }
        }

        /**
         * Check if a class field has a dangling underscore
         * @param {ASTNode} node node to evaluate
         * @returns {void}
         * @private
         */
        function checkForDanglingUnderscoreInClassField(node) {
            const identifier = node.key.name;

            if (typeof identifier !== "undefined" && hasDanglingUnderscore(identifier) &&
                enforceInClassFields &&
                !isAllowed(identifier)) {
                context.report({
                    node,
                    messageId: "unexpectedUnderscore",
                    data: {
                        identifier: node.key.type === "PrivateIdentifier"
                            ? `#${identifier}`
                            : identifier
                    }
                });
            }
        }

        //--------------------------------------------------------------------------
        // Public API
        //--------------------------------------------------------------------------

        return {
            FunctionDeclaration: checkForDanglingUnderscoreInFunction,
            VariableDeclarator: checkForDanglingUnderscoreInVariableExpression,
            MemberExpression: checkForDanglingUnderscoreInMemberExpression,
            MethodDefinition: checkForDanglingUnderscoreInMethod,
            PropertyDefinition: checkForDanglingUnderscoreInClassField,
            Property: checkForDanglingUnderscoreInMethod,
            FunctionExpression: checkForDanglingUnderscoreInFunction,
            ArrowFunctionExpression: checkForDanglingUnderscoreInFunction
        };

    }
};


code:
/**
 * @fileoverview Rule to spot scenarios where a newline looks like it is ending a statement, but is not.
 * @author Glen Mailer
 */
"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const astUtils = require("./utils/ast-utils");

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

/** @type {import('../shared/types').Rule} */
module.exports = {
    meta: {
        type: "problem",

        docs: {
            description: "Disallow confusing multiline expressions",
            recommended: true,
            url: "https://eslint.org/docs/latest/rules/no-unexpected-multiline"
        },

        schema: [],
        messages: {
            function: "Unexpected newline between function and ( of function call.",
            property: "Unexpected newline between object and [ of property access.",
            taggedTemplate: "Unexpected newline between template tag and template literal.",
            division: "Unexpected newline between numerator and division operator."
        }
    },

    create(context) {

        const REGEX_FLAG_MATCHER = /^[gimsuy]+$/u;

        const sourceCode = context.sourceCode;

        /**
         * Check to see if there is a newline between the node and the following open bracket
         * line's expression
         * @param {ASTNode} node The node to check.
         * @param {string} messageId The error messageId to use.
         * @returns {void}
         * @private
         */
        function checkForBreakAfter(node, messageId) {
            const openParen = sourceCode.getTokenAfter(node, astUtils.isNotClosingParenToken);
            const nodeExpressionEnd = sourceCode.getTokenBefore(openParen);

            if (openParen.loc.start.line !== nodeExpressionEnd.loc.end.line) {
                context.report({
                    node,
                    loc: openParen.loc,
                    messageId
                });
            }
        }

        //--------------------------------------------------------------------------
        // Public API
        //--------------------------------------------------------------------------

        return {

            MemberExpression(node) {
                if (!node.computed || node.optional) {
                    return;
                }
                checkForBreakAfter(node.object, "property");
            },

            TaggedTemplateExpression(node) {
                const { quasi } = node;

                // handles common tags, parenthesized tags, and typescript's generic type arguments
                const tokenBefore = sourceCode.getTokenBefore(quasi);

                if (tokenBefore.loc.end.line !== quasi.loc.start.line) {
                    context.report({
                        node,
                        loc: {
                            start: quasi.loc.start,
                            end: {
                                line: quasi.loc.start.line,
                                column: quasi.loc.start.column + 1
                            }
                        },
                        messageId: "taggedTemplate"
                    });
                }
            },

            CallExpression(node) {
                if (node.arguments.length === 0 || node.optional) {
                    return;
                }
                checkForBreakAfter(node.callee, "function");
            },

            "BinaryExpression[operator='/'] > BinaryExpression[operator='/'].left"(node) {
                const secondSlash = sourceCode.getTokenAfter(node, token => token.value === "/");
                const tokenAfterOperator = sourceCode.getTokenAfter(secondSlash);

                if (
                    tokenAfterOperator.type === "Identifier" &&
                    REGEX_FLAG_MATCHER.test(tokenAfterOperator.value) &&
                    secondSlash.range[1] === tokenAfterOperator.range[0]
                ) {
                    checkForBreakAfter(node.left, "division");
                }
            }
        };

    }
};


code:
/**
 * @fileoverview Rule to disallow use of unmodified expressions in loop conditions
 * @author Toru Nagashima
 */

"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const Traverser = require("../shared/traverser"),
    astUtils = require("./utils/ast-utils");

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

const SENTINEL_PATTERN = /(?:(?:Call|Class|Function|Member|New|Yield)Expression|Statement|Declaration)$/u;
const LOOP_PATTERN = /^(?:DoWhile|For|While)Statement$/u; // for-in/of statements don't have `test` property.
const GROUP_PATTERN = /^(?:BinaryExpression|ConditionalExpression)$/u;
const SKIP_PATTERN = /^(?:ArrowFunction|Class|Function)Expression$/u;
const DYNAMIC_PATTERN = /^(?:Call|Member|New|TaggedTemplate|Yield)Expression$/u;

/**
 * @typedef {Object} LoopConditionInfo
 * @property {eslint-scope.Reference} reference - The reference.
 * @property {ASTNode} group - BinaryExpression or ConditionalExpression nodes
 *      that the reference is belonging to.
 * @property {Function} isInLoop - The predicate which checks a given reference
 *      is in this loop.
 * @property {boolean} modified - The flag that the reference is modified in
 *      this loop.
 */

/**
 * Checks whether or not a given reference is a write reference.
 * @param {eslint-scope.Reference} reference A reference to check.
 * @returns {boolean} `true` if the reference is a write reference.
 */
function isWriteReference(reference) {
    if (reference.init) {
        const def = reference.resolved && reference.resolved.defs[0];

        if (!def || def.type !== "Variable" || def.parent.kind !== "var") {
            return false;
        }
    }
    return reference.isWrite();
}

/**
 * Checks whether or not a given loop condition info does not have the modified
 * flag.
 * @param {LoopConditionInfo} condition A loop condition info to check.
 * @returns {boolean} `true` if the loop condition info is "unmodified".
 */
function isUnmodified(condition) {
    return !condition.modified;
}

/**
 * Checks whether or not a given loop condition info does not have the modified
 * flag and does not have the group this condition belongs to.
 * @param {LoopConditionInfo} condition A loop condition info to check.
 * @returns {boolean} `true` if the loop condition info is "unmodified".
 */
function isUnmodifiedAndNotBelongToGroup(condition) {
    return !(condition.modified || condition.group);
}

/**
 * Checks whether or not a given reference is inside of a given node.
 * @param {ASTNode} node A node to check.
 * @param {eslint-scope.Reference} reference A reference to check.
 * @returns {boolean} `true` if the reference is inside of the node.
 */
function isInRange(node, reference) {
    const or = node.range;
    const ir = reference.identifier.range;

    return or[0] <= ir[0] && ir[1] <= or[1];
}

/**
 * Checks whether or not a given reference is inside of a loop node's condition.
 * @param {ASTNode} node A node to check.
 * @param {eslint-scope.Reference} reference A reference to check.
 * @returns {boolean} `true` if the reference is inside of the loop node's
 *      condition.
 */
const isInLoop = {
    WhileStatement: isInRange,
    DoWhileStatement: isInRange,
    ForStatement(node, reference) {
        return (
            isInRange(node, reference) &&
            !(node.init && isInRange(node.init, reference))
        );
    }
};

/**
 * Gets the function which encloses a given reference.
 * This supports only FunctionDeclaration.
 * @param {eslint-scope.Reference} reference A reference to get.
 * @returns {ASTNode|null} The function node or null.
 */
function getEncloseFunctionDeclaration(reference) {
    let node = reference.identifier;

    while (node) {
        if (node.type === "FunctionDeclaration") {
            return node.id ? node : null;
        }

        node = node.parent;
    }

    return null;
}

/**
 * Updates the "modified" flags of given loop conditions with given modifiers.
 * @param {LoopConditionInfo[]} conditions The loop conditions to be updated.
 * @param {eslint-scope.Reference[]} modifiers The references to update.
 * @returns {void}
 */
function updateModifiedFlag(conditions, modifiers) {

    for (let i = 0; i < conditions.length; ++i) {
        const condition = conditions[i];

        for (let j = 0; !condition.modified && j < modifiers.length; ++j) {
            const modifier = modifiers[j];
            let funcNode, funcVar;

            /*
             * Besides checking for the condition being in the loop, we want to
             * check the function that this modifier is belonging to is called
             * in the loop.
             * FIXME: This should probably be extracted to a function.
             */
            const inLoop = condition.isInLoop(modifier) || Boolean(
                (funcNode = getEncloseFunctionDeclaration(modifier)) &&
                (funcVar = astUtils.getVariableByName(modifier.from.upper, funcNode.id.name)) &&
                funcVar.references.some(condition.isInLoop)
            );

            condition.modified = inLoop;
        }
    }
}

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

/** @type {import('../shared/types').Rule} */
module.exports = {
    meta: {
        type: "problem",

        docs: {
            description: "Disallow unmodified loop conditions",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-unmodified-loop-condition"
        },

        schema: [],

        messages: {
            loopConditionNotModified: "'{{name}}' is not modified in this loop."
        }
    },

    create(context) {
        const sourceCode = context.sourceCode;
        let groupMap = null;

        /**
         * Reports a given condition info.
         * @param {LoopConditionInfo} condition A loop condition info to report.
         * @returns {void}
         */
        function report(condition) {
            const node = condition.reference.identifier;

            context.report({
                node,
                messageId: "loopConditionNotModified",
                data: node
            });
        }

        /**
         * Registers given conditions to the group the condition belongs to.
         * @param {LoopConditionInfo[]} conditions A loop condition info to
         *      register.
         * @returns {void}
         */
        function registerConditionsToGroup(conditions) {
            for (let i = 0; i < conditions.length; ++i) {
                const condition = conditions[i];

                if (condition.group) {
                    let group = groupMap.get(condition.group);

                    if (!group) {
                        group = [];
                        groupMap.set(condition.group, group);
                    }
                    group.push(condition);
                }
            }
        }

        /**
         * Reports references which are inside of unmodified groups.
         * @param {LoopConditionInfo[]} conditions A loop condition info to report.
         * @returns {void}
         */
        function checkConditionsInGroup(conditions) {
            if (conditions.every(isUnmodified)) {
                conditions.forEach(report);
            }
        }

        /**
         * Checks whether or not a given group node has any dynamic elements.
         * @param {ASTNode} root A node to check.
         *      This node is one of BinaryExpression or ConditionalExpression.
         * @returns {boolean} `true` if the node is dynamic.
         */
        function hasDynamicExpressions(root) {
            let retv = false;

            Traverser.traverse(root, {
                visitorKeys: sourceCode.visitorKeys,
                enter(node) {
                    if (DYNAMIC_PATTERN.test(node.type)) {
                        retv = true;
                        this.break();
                    } else if (SKIP_PATTERN.test(node.type)) {
                        this.skip();
                    }
                }
            });

            return retv;
        }

        /**
         * Creates the loop condition information from a given reference.
         * @param {eslint-scope.Reference} reference A reference to create.
         * @returns {LoopConditionInfo|null} Created loop condition info, or null.
         */
        function toLoopCondition(reference) {
            if (reference.init) {
                return null;
            }

            let group = null;
            let child = reference.identifier;
            let node = child.parent;

            while (node) {
                if (SENTINEL_PATTERN.test(node.type)) {
                    if (LOOP_PATTERN.test(node.type) && node.test === child) {

                        // This reference is inside of a loop condition.
                        return {
                            reference,
                            group,
                            isInLoop: isInLoop[node.type].bind(null, node),
                            modified: false
                        };
                    }

                    // This reference is outside of a loop condition.
                    break;
                }

                /*
                 * If it's inside of a group, OK if either operand is modified.
                 * So stores the group this reference belongs to.
                 */
                if (GROUP_PATTERN.test(node.type)) {

                    // If this expression is dynamic, no need to check.
                    if (hasDynamicExpressions(node)) {
                        break;
                    } else {
                        group = node;
                    }
                }

                child = node;
                node = node.parent;
            }

            return null;
        }

        /**
         * Finds unmodified references which are inside of a loop condition.
         * Then reports the references which are outside of groups.
         * @param {eslint-scope.Variable} variable A variable to report.
         * @returns {void}
         */
        function checkReferences(variable) {

            // Gets references that exist in loop conditions.
            const conditions = variable
                .references
                .map(toLoopCondition)
                .filter(Boolean);

            if (conditions.length === 0) {
                return;
            }

            // Registers the conditions to belonging groups.
            registerConditionsToGroup(conditions);

            // Check the conditions are modified.
            const modifiers = variable.references.filter(isWriteReference);

            if (modifiers.length > 0) {
                updateModifiedFlag(conditions, modifiers);
            }

            /*
             * Reports the conditions which are not belonging to groups.
             * Others will be reported after all variables are done.
             */
            conditions
                .filter(isUnmodifiedAndNotBelongToGroup)
                .forEach(report);
        }

        return {
            "Program:exit"(node) {
                const queue = [sourceCode.getScope(node)];

                groupMap = new Map();

                let scope;

                while ((scope = queue.pop())) {
                    queue.push(...scope.childScopes);
                    scope.variables.forEach(checkReferences);
                }

                groupMap.forEach(checkConditionsInGroup);
                groupMap = null;
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to flag no-unneeded-ternary
 * @author Gyandeep Singh
 */

"use strict";

const astUtils = require("./utils/ast-utils");

// Operators that always result in a boolean value
const BOOLEAN_OPERATORS = new Set(["==", "===", "!=", "!==", ">", ">=", "<", "<=", "in", "instanceof"]);
const OPERATOR_INVERSES = {
    "==": "!=",
    "!=": "==",
    "===": "!==",
    "!==": "==="

    // Operators like < and >= are not true inverses, since both will return false with NaN.
};
const OR_PRECEDENCE = astUtils.getPrecedence({ type: "LogicalExpression", operator: "||" });

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

/** @type {import('../shared/types').Rule} */
module.exports = {
    meta: {
        type: "suggestion",

        docs: {
            description: "Disallow ternary operators when simpler alternatives exist",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-unneeded-ternary"
        },

        schema: [
            {
                type: "object",
                properties: {
                    defaultAssignment: {
                        type: "boolean",
                        default: true
                    }
                },
                additionalProperties: false
            }
        ],

        fixable: "code",

        messages: {
            unnecessaryConditionalExpression: "Unnecessary use of boolean literals in conditional expression.",
            unnecessaryConditionalAssignment: "Unnecessary use of conditional expression for default assignment."
        }
    },

    create(context) {
        const options = context.options[0] || {};
        const defaultAssignment = options.defaultAssignment !== false;
        const sourceCode = context.sourceCode;

        /**
         * Test if the node is a boolean literal
         * @param {ASTNode} node The node to report.
         * @returns {boolean} True if the its a boolean literal
         * @private
         */
        function isBooleanLiteral(node) {
            return node.type === "Literal" && typeof node.value === "boolean";
        }

        /**
         * Creates an expression that represents the boolean inverse of the expression represented by the original node
         * @param {ASTNode} node A node representing an expression
         * @returns {string} A string representing an inverted expression
         */
        function invertExpression(node) {
            if (node.type === "BinaryExpression" && Object.prototype.hasOwnProperty.call(OPERATOR_INVERSES, node.operator)) {
                const operatorToken = sourceCode.getFirstTokenBetween(
                    node.left,
                    node.right,
                    token => token.value === node.operator
                );
                const text = sourceCode.getText();

                return text.slice(node.range[0],
                    operatorToken.range[0]) + OPERATOR_INVERSES[node.operator] + text.slice(operatorToken.range[1], node.range[1]);
            }

            if (astUtils.getPrecedence(node) < astUtils.getPrecedence({ type: "UnaryExpression" })) {
                return `!(${astUtils.getParenthesisedText(sourceCode, node)})`;
            }
            return `!${astUtils.getParenthesisedText(sourceCode, node)}`;
        }

        /**
         * Tests if a given node always evaluates to a boolean value
         * @param {ASTNode} node An expression node
         * @returns {boolean} True if it is determined that the node will always evaluate to a boolean value
         */
        function isBooleanExpression(node) {
            return node.type === "BinaryExpression" && BOOLEAN_OPERATORS.has(node.operator) ||
                node.type === "UnaryExpression" && node.operator === "!";
        }

        /**
         * Test if the node matches the pattern id ? id : expression
         * @param {ASTNode} node The ConditionalExpression to check.
         * @returns {boolean} True if the pattern is matched, and false otherwise
         * @private
         */
        function matchesDefaultAssignment(node) {
            return node.test.type === "Identifier" &&
                   node.consequent.type === "Identifier" &&
                   node.test.name === node.consequent.name;
        }

        return {

            ConditionalExpression(node) {
                if (isBooleanLiteral(node.alternate) && isBooleanLiteral(node.consequent)) {
                    context.report({
                        node,
                        messageId: "unnecessaryConditionalExpression",
                        fix(fixer) {
                            if (node.consequent.value === node.alternate.value) {

                                // Replace `foo ? true : true` with just `true`, but don't replace `foo() ? true : true`
                                return node.test.type === "Identifier" ? fixer.replaceText(node, node.consequent.value.toString()) : null;
                            }
                            if (node.alternate.value) {

                                // Replace `foo() ? false : true` with `!(foo())`
                                return fixer.replaceText(node, invertExpression(node.test));
                            }

                            // Replace `foo ? true : false` with `foo` if `foo` is guaranteed to be a boolean, or `!!foo` otherwise.

                            return fixer.replaceText(node, isBooleanExpression(node.test) ? astUtils.getParenthesisedText(sourceCode, node.test) : `!${invertExpression(node.test)}`);
                        }
                    });
                } else if (!defaultAssignment && matchesDefaultAssignment(node)) {
                    context.report({
                        node,
                        messageId: "unnecessaryConditionalAssignment",
                        fix(fixer) {
                            const shouldParenthesizeAlternate =
                                (
                                    astUtils.getPrecedence(node.alternate) < OR_PRECEDENCE ||
                                    astUtils.isCoalesceExpression(node.alternate)
                                ) &&
                                !astUtils.isParenthesised(sourceCode, node.alternate);
                            const alternateText = shouldParenthesizeAlternate
                                ? `(${sourceCode.getText(node.alternate)})`
                                : astUtils.getParenthesisedText(sourceCode, node.alternate);
                            const testText = astUtils.getParenthesisedText(sourceCode, node.test);

                            return fixer.replaceText(node, `${testText} || ${alternateText}`);
                        }
                    });
                }
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to disallow loops with a body that allows only one iteration
 * @author Milos Djermanovic
 */

"use strict";

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

const allLoopTypes = ["WhileStatement", "DoWhileStatement", "ForStatement", "ForInStatement", "ForOfStatement"];

/**
 * Checks all segments in a set and returns true if any are reachable.
 * @param {Set<CodePathSegment>} segments The segments to check.
 * @returns {boolean} True if any segment is reachable; false otherwise.
 */
function isAnySegmentReachable(segments) {

    for (const segment of segments) {
        if (segment.reachable) {
            return true;
        }
    }

    return false;
}

/**
 * Determines whether the given node is the first node in the code path to which a loop statement
 * 'loops' for the next iteration.
 * @param {ASTNode} node The node to check.
 * @returns {boolean} `true` if the node is a looping target.
 */
function isLoopingTarget(node) {
    const parent = node.parent;

    if (parent) {
        switch (parent.type) {
            case "WhileStatement":
                return node === parent.test;
            case "DoWhileStatement":
                return node === parent.body;
            case "ForStatement":
                return node === (parent.update || parent.test || parent.body);
            case "ForInStatement":
            case "ForOfStatement":
                return node === parent.left;

            // no default
        }
    }

    return false;
}

/**
 * Creates an array with elements from the first given array that are not included in the second given array.
 * @param {Array} arrA The array to compare from.
 * @param {Array} arrB The array to compare against.
 * @returns {Array} a new array that represents `arrA \ arrB`.
 */
function getDifference(arrA, arrB) {
    return arrA.filter(a => !arrB.includes(a));
}

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

/** @type {import('../shared/types').Rule} */
module.exports = {
    meta: {
        type: "problem",

        docs: {
            description: "Disallow loops with a body that allows only one iteration",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-unreachable-loop"
        },

        schema: [{
            type: "object",
            properties: {
                ignore: {
                    type: "array",
                    items: {
                        enum: allLoopTypes
                    },
                    uniqueItems: true
                }
            },
            additionalProperties: false
        }],

        messages: {
            invalid: "Invalid loop. Its body allows only one iteration."
        }
    },

    create(context) {
        const ignoredLoopTypes = context.options[0] && context.options[0].ignore || [],
            loopTypesToCheck = getDifference(allLoopTypes, ignoredLoopTypes),
            loopSelector = loopTypesToCheck.join(","),
            loopsByTargetSegments = new Map(),
            loopsToReport = new Set();

        const codePathSegments = [];
        let currentCodePathSegments = new Set();

        return {

            onCodePathStart() {
                codePathSegments.push(currentCodePathSegments);
                currentCodePathSegments = new Set();
            },

            onCodePathEnd() {
                currentCodePathSegments = codePathSegments.pop();
            },

            onUnreachableCodePathSegmentStart(segment) {
                currentCodePathSegments.add(segment);
            },

            onUnreachableCodePathSegmentEnd(segment) {
                currentCodePathSegments.delete(segment);
            },

            onCodePathSegmentEnd(segment) {
                currentCodePathSegments.delete(segment);
            },

            onCodePathSegmentStart(segment, node) {

                currentCodePathSegments.add(segment);

                if (isLoopingTarget(node)) {
                    const loop = node.parent;

                    loopsByTargetSegments.set(segment, loop);
                }
            },

            onCodePathSegmentLoop(_, toSegment, node) {
                const loop = loopsByTargetSegments.get(toSegment);

                /**
                 * The second iteration is reachable, meaning that the loop is valid by the logic of this rule,
                 * only if there is at least one loop event with the appropriate target (which has been already
                 * determined in the `loopsByTargetSegments` map), raised from either:
                 *
                 * - the end of the loop's body (in which case `node === loop`)
                 * - a `continue` statement
                 *
                 * This condition skips loop events raised from `ForInStatement > .right` and `ForOfStatement > .right` nodes.
                 */
                if (node === loop || node.type === "ContinueStatement") {

                    // Removes loop if it exists in the set. Otherwise, `Set#delete` has no effect and doesn't throw.
                    loopsToReport.delete(loop);
                }
            },

            [loopSelector](node) {

                /**
                 * Ignore unreachable loop statements to avoid unnecessary complexity in the implementation, or false positives otherwise.
                 * For unreachable segments, the code path analysis does not raise events required for this implementation.
                 */
                if (isAnySegmentReachable(currentCodePathSegments)) {
                    loopsToReport.add(node);
                }
            },

            "Program:exit"() {
                loopsToReport.forEach(
                    node => context.report({ node, messageId: "invalid" })
                );
            }
        };
    }
};


code:
/**
 * @fileoverview Checks for unreachable code due to return, throws, break, and continue.
 * @author Joel Feenstra
 */
"use strict";

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

/**
 * @typedef {Object} ConstructorInfo
 * @property {ConstructorInfo | null} upper Info about the constructor that encloses this constructor.
 * @property {boolean} hasSuperCall The flag about having `super()` expressions.
 */

/**
 * Checks whether or not a given variable declarator has the initializer.
 * @param {ASTNode} node A VariableDeclarator node to check.
 * @returns {boolean} `true` if the node has the initializer.
 */
function isInitialized(node) {
    return Boolean(node.init);
}

/**
 * Checks all segments in a set and returns true if all are unreachable.
 * @param {Set<CodePathSegment>} segments The segments to check.
 * @returns {boolean} True if all segments are unreachable; false otherwise.
 */
function areAllSegmentsUnreachable(segments) {

    for (const segment of segments) {
        if (segment.reachable) {
            return false;
        }
    }

    return true;
}

/**
 * The class to distinguish consecutive unreachable statements.
 */
class ConsecutiveRange {
    constructor(sourceCode) {
        this.sourceCode = sourceCode;
        this.startNode = null;
        this.endNode = null;
    }

    /**
     * The location object of this range.
     * @type {Object}
     */
    get location() {
        return {
            start: this.startNode.loc.start,
            end: this.endNode.loc.end
        };
    }

    /**
     * `true` if this range is empty.
     * @type {boolean}
     */
    get isEmpty() {
        return !(this.startNode && this.endNode);
    }

    /**
     * Checks whether the given node is inside of this range.
     * @param {ASTNode|Token} node The node to check.
     * @returns {boolean} `true` if the node is inside of this range.
     */
    contains(node) {
        return (
            node.range[0] >= this.startNode.range[0] &&
            node.range[1] <= this.endNode.range[1]
        );
    }

    /**
     * Checks whether the given node is consecutive to this range.
     * @param {ASTNode} node The node to check.
     * @returns {boolean} `true` if the node is consecutive to this range.
     */
    isConsecutive(node) {
        return this.contains(this.sourceCode.getTokenBefore(node));
    }

    /**
     * Merges the given node to this range.
     * @param {ASTNode} node The node to merge.
     * @returns {void}
     */
    merge(node) {
        this.endNode = node;
    }

    /**
     * Resets this range by the given node or null.
     * @param {ASTNode|null} node The node to reset, or null.
     * @returns {void}
     */
    reset(node) {
        this.startNode = this.endNode = node;
    }
}

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

/** @type {import('../shared/types').Rule} */
module.exports = {
    meta: {
        type: "problem",

        docs: {
            description: "Disallow unreachable code after `return`, `throw`, `continue`, and `break` statements",
            recommended: true,
            url: "https://eslint.org/docs/latest/rules/no-unreachable"
        },

        schema: [],

        messages: {
            unreachableCode: "Unreachable code."
        }
    },

    create(context) {

        /** @type {ConstructorInfo | null} */
        let constructorInfo = null;

        /** @type {ConsecutiveRange} */
        const range = new ConsecutiveRange(context.sourceCode);

        /** @type {Array<Set<CodePathSegment>>} */
        const codePathSegments = [];

        /** @type {Set<CodePathSegment>} */
        let currentCodePathSegments = new Set();

        /**
         * Reports a given node if it's unreachable.
         * @param {ASTNode} node A statement node to report.
         * @returns {void}
         */
        function reportIfUnreachable(node) {
            let nextNode = null;

            if (node && (node.type === "PropertyDefinition" || areAllSegmentsUnreachable(currentCodePathSegments))) {

                // Store this statement to distinguish consecutive statements.
                if (range.isEmpty) {
                    range.reset(node);
                    return;
                }

                // Skip if this statement is inside of the current range.
                if (range.contains(node)) {
                    return;
                }

                // Merge if this statement is consecutive to the current range.
                if (range.isConsecutive(node)) {
                    range.merge(node);
                    return;
                }

                nextNode = node;
            }

            /*
             * Report the current range since this statement is reachable or is
             * not consecutive to the current range.
             */
            if (!range.isEmpty) {
                context.report({
                    messageId: "unreachableCode",
                    loc: range.location,
                    node: range.startNode
                });
            }

            // Update the current range.
            range.reset(nextNode);
        }

        return {

            // Manages the current code path.
            onCodePathStart() {
                codePathSegments.push(currentCodePathSegments);
                currentCodePathSegments = new Set();
            },

            onCodePathEnd() {
                currentCodePathSegments = codePathSegments.pop();
            },

            onUnreachableCodePathSegmentStart(segment) {
                currentCodePathSegments.add(segment);
            },

            onUnreachableCodePathSegmentEnd(segment) {
                currentCodePathSegments.delete(segment);
            },

            onCodePathSegmentEnd(segment) {
                currentCodePathSegments.delete(segment);
            },

            onCodePathSegmentStart(segment) {
                currentCodePathSegments.add(segment);
            },

            // Registers for all statement nodes (excludes FunctionDeclaration).
            BlockStatement: reportIfUnreachable,
            BreakStatement: reportIfUnreachable,
            ClassDeclaration: reportIfUnreachable,
            ContinueStatement: reportIfUnreachable,
            DebuggerStatement: reportIfUnreachable,
            DoWhileStatement: reportIfUnreachable,
            ExpressionStatement: reportIfUnreachable,
            ForInStatement: reportIfUnreachable,
            ForOfStatement: reportIfUnreachable,
            ForStatement: reportIfUnreachable,
            IfStatement: reportIfUnreachable,
            ImportDeclaration: reportIfUnreachable,
            LabeledStatement: reportIfUnreachable,
            ReturnStatement: reportIfUnreachable,
            SwitchStatement: reportIfUnreachable,
            ThrowStatement: reportIfUnreachable,
            TryStatement: reportIfUnreachable,

            VariableDeclaration(node) {
                if (node.kind !== "var" || node.declarations.some(isInitialized)) {
                    reportIfUnreachable(node);
                }
            },

            WhileStatement: reportIfUnreachable,
            WithStatement: reportIfUnreachable,
            ExportNamedDeclaration: reportIfUnreachable,
            ExportDefaultDeclaration: reportIfUnreachable,
            ExportAllDeclaration: reportIfUnreachable,

            "Program:exit"() {
                reportIfUnreachable();
            },

            /*
             * Instance fields defined in a subclass are never created if the constructor of the subclass
             * doesn't call `super()`, so their definitions are unreachable code.
             */
            "MethodDefinition[kind='constructor']"() {
                constructorInfo = {
                    upper: constructorInfo,
                    hasSuperCall: false
                };
            },
            "MethodDefinition[kind='constructor']:exit"(node) {
                const { hasSuperCall } = constructorInfo;

                constructorInfo = constructorInfo.upper;

                // skip typescript constructors without the body
                if (!node.value.body) {
                    return;
                }

                const classDefinition = node.parent.parent;

                if (classDefinition.superClass && !hasSuperCall) {
                    for (const element of classDefinition.body.body) {
                        if (element.type === "PropertyDefinition" && !element.static) {
                            reportIfUnreachable(element);
                        }
                    }
                }
            },
            "CallExpression > Super.callee"() {
                if (constructorInfo) {
                    constructorInfo.hasSuperCall = true;
                }
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to flag unsafe statements in finally block
 * @author Onur Temizkan
 */

"use strict";

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

const SENTINEL_NODE_TYPE_RETURN_THROW = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression)$/u;
const SENTINEL_NODE_TYPE_BREAK = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement|SwitchStatement)$/u;
const SENTINEL_NODE_TYPE_CONTINUE = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement)$/u;

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

/** @type {import('../shared/types').Rule} */
module.exports = {
    meta: {
        type: "problem",

        docs: {
            description: "Disallow control flow statements in `finally` blocks",
            recommended: true,
            url: "https://eslint.org/docs/latest/rules/no-unsafe-finally"
        },

        schema: [],

        messages: {
            unsafeUsage: "Unsafe usage of {{nodeType}}."
        }
    },
    create(context) {

        /**
         * Checks if the node is the finalizer of a TryStatement
         * @param {ASTNode} node node to check.
         * @returns {boolean} - true if the node is the finalizer of a TryStatement
         */
        function isFinallyBlock(node) {
            return node.parent.type === "TryStatement" && node.parent.finalizer === node;
        }

        /**
         * Climbs up the tree if the node is not a sentinel node
         * @param {ASTNode} node node to check.
         * @param {string} label label of the break or continue statement
         * @returns {boolean} - return whether the node is a finally block or a sentinel node
         */
        function isInFinallyBlock(node, label) {
            let labelInside = false;
            let sentinelNodeType;

            if (node.type === "BreakStatement" && !node.label) {
                sentinelNodeType = SENTINEL_NODE_TYPE_BREAK;
            } else if (node.type === "ContinueStatement") {
                sentinelNodeType = SENTINEL_NODE_TYPE_CONTINUE;
            } else {
                sentinelNodeType = SENTINEL_NODE_TYPE_RETURN_THROW;
            }

            for (
                let currentNode = node;
                currentNode && !sentinelNodeType.test(currentNode.type);
                currentNode = currentNode.parent
            ) {
                if (currentNode.parent.label && label && (currentNode.parent.label.name === label.name)) {
                    labelInside = true;
                }
                if (isFinallyBlock(currentNode)) {
                    if (label && labelInside) {
                        return false;
                    }
                    return true;
                }
            }
            return false;
        }

        /**
         * Checks whether the possibly-unsafe statement is inside a finally block.
         * @param {ASTNode} node node to check.
         * @returns {void}
         */
        function check(node) {
            if (isInFinallyBlock(node, node.label)) {
                context.report({
                    messageId: "unsafeUsage",
                    data: {
                        nodeType: node.type
                    },
                    node,
                    line: node.loc.line,
                    column: node.loc.column
                });
            }
        }

        return {
            ReturnStatement: check,
            ThrowStatement: check,
            BreakStatement: check,
            ContinueStatement: check
        };
    }
};


code:
/**
 * @fileoverview Rule to disallow negating the left operand of relational operators
 * @author Toru Nagashima
 */

"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const astUtils = require("./utils/ast-utils");

//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------

/**
 * Checks whether the given operator is `in` or `instanceof`
 * @param {string} op The operator type to check.
 * @returns {boolean} `true` if the operator is `in` or `instanceof`
 */
function isInOrInstanceOfOperator(op) {
    return op === "in" || op === "instanceof";
}

/**
 * Checks whether the given operator is an ordering relational operator or not.
 * @param {string} op The operator type to check.
 * @returns {boolean} `true` if the operator is an ordering relational operator.
 */
function isOrderingRelationalOperator(op) {
    return op === "<" || op === ">" || op === ">=" || op === "<=";
}

/**
 * Checks whether the given node is a logical negation expression or not.
 * @param {ASTNode} node The node to check.
 * @returns {boolean} `true` if the node is a logical negation expression.
 */
function isNegation(node) {
    return node.type === "UnaryExpression" && node.operator === "!";
}

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

/** @type {import('../shared/types').Rule} */
module.exports = {
    meta: {
        type: "problem",

        docs: {
            description: "Disallow negating the left operand of relational operators",
            recommended: true,
            url: "https://eslint.org/docs/latest/rules/no-unsafe-negation"
        },

        hasSuggestions: true,

        schema: [
            {
                type: "object",
                properties: {
                    enforceForOrderingRelations: {
                        type: "boolean",
                        default: false
                    }
                },
                additionalProperties: false
            }
        ],

        fixable: null,

        messages: {
            unexpected: "Unexpected negating the left operand of '{{operator}}' operator.",
            suggestNegatedExpression: "Negate '{{operator}}' expression instead of its left operand. This changes the current behavior.",
            suggestParenthesisedNegation: "Wrap negation in '()' to make the intention explicit. This preserves the current behavior."
        }
    },

    create(context) {
        const sourceCode = context.sourceCode;
        const options = context.options[0] || {};
        const enforceForOrderingRelations = options.enforceForOrderingRelations === true;

        return {
            BinaryExpression(node) {
                const operator = node.operator;
                const orderingRelationRuleApplies = enforceForOrderingRelations && isOrderingRelationalOperator(operator);

                if (
                    (isInOrInstanceOfOperator(operator) || orderingRelationRuleApplies) &&
                    isNegation(node.left) &&
                    !astUtils.isParenthesised(sourceCode, node.left)
                ) {
                    context.report({
                        node,
                        loc: node.left.loc,
                        messageId: "unexpected",
                        data: { operator },
                        suggest: [
                            {
                                messageId: "suggestNegatedExpression",
                                data: { operator },
                                fix(fixer) {
                                    const negationToken = sourceCode.getFirstToken(node.left);
                                    const fixRange = [negationToken.range[1], node.range[1]];
                                    const text = sourceCode.text.slice(fixRange[0], fixRange[1]);

                                    return fixer.replaceTextRange(fixRange, `(${text})`);
                                }
                            },
                            {
                                messageId: "suggestParenthesisedNegation",
                                fix(fixer) {
                                    return fixer.replaceText(node.left, `(${sourceCode.getText(node.left)})`);
                                }
                            }
                        ]
                    });
                }
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to disallow unsafe optional chaining
 * @author Yeon JuAn
 */

"use strict";

const UNSAFE_ARITHMETIC_OPERATORS = new Set(["+", "-", "/", "*", "%", "**"]);
const UNSAFE_ASSIGNMENT_OPERATORS = new Set(["+=", "-=", "/=", "*=", "%=", "**="]);
const UNSAFE_RELATIONAL_OPERATORS = new Set(["in", "instanceof"]);

/**
 * Checks whether a node is a destructuring pattern or not
 * @param {ASTNode} node node to check
 * @returns {boolean} `true` if a node is a destructuring pattern, otherwise `false`
 */
function isDestructuringPattern(node) {
    return node.type === "ObjectPattern" || node.type === "ArrayPattern";
}

/** @type {import('../shared/types').Rule} */
module.exports = {
    meta: {
        type: "problem",

        docs: {
            description: "Disallow use of optional chaining in contexts where the `undefined` value is not allowed",
            recommended: true,
            url: "https://eslint.org/docs/latest/rules/no-unsafe-optional-chaining"
        },
        schema: [{
            type: "object",
            properties: {
                disallowArithmeticOperators: {
                    type: "boolean",
                    default: false
                }
            },
            additionalProperties: false
        }],
        fixable: null,
        messages: {
            unsafeOptionalChain: "Unsafe usage of optional chaining. If it short-circuits with 'undefined' the evaluation will throw TypeError.",
            unsafeArithmetic: "Unsafe arithmetic operation on optional chaining. It can result in NaN."
        }
    },

    create(context) {
        const options = context.options[0] || {};
        const disallowArithmeticOperators = (options.disallowArithmeticOperators) || false;

        /**
         * Reports unsafe usage of optional chaining
         * @param {ASTNode} node node to report
         * @returns {void}
         */
        function reportUnsafeUsage(node) {
            context.report({
                messageId: "unsafeOptionalChain",
                node
            });
        }

        /**
         * Reports unsafe arithmetic operation on optional chaining
         * @param {ASTNode} node node to report
         * @returns {void}
         */
        function reportUnsafeArithmetic(node) {
            context.report({
                messageId: "unsafeArithmetic",
                node
            });
        }

        /**
         * Checks and reports if a node can short-circuit with `undefined` by optional chaining.
         * @param {ASTNode} [node] node to check
         * @param {Function} reportFunc report function
         * @returns {void}
         */
        function checkUndefinedShortCircuit(node, reportFunc) {
            if (!node) {
                return;
            }
            switch (node.type) {
                case "LogicalExpression":
                    if (node.operator === "||" || node.operator === "??") {
                        checkUndefinedShortCircuit(node.right, reportFunc);
                    } else if (node.operator === "&&") {
                        checkUndefinedShortCircuit(node.left, reportFunc);
                        checkUndefinedShortCircuit(node.right, reportFunc);
                    }
                    break;
                case "SequenceExpression":
                    checkUndefinedShortCircuit(
                        node.expressions[node.expressions.length - 1],
                        reportFunc
                    );
                    break;
                case "ConditionalExpression":
                    checkUndefinedShortCircuit(node.consequent, reportFunc);
                    checkUndefinedShortCircuit(node.alternate, reportFunc);
                    break;
                case "AwaitExpression":
                    checkUndefinedShortCircuit(node.argument, reportFunc);
                    break;
                case "ChainExpression":
                    reportFunc(node);
                    break;
                default:
                    break;
            }
        }

        /**
         * Checks unsafe usage of optional chaining
         * @param {ASTNode} node node to check
         * @returns {void}
         */
        function checkUnsafeUsage(node) {
            checkUndefinedShortCircuit(node, reportUnsafeUsage);
        }

        /**
         * Checks unsafe arithmetic operations on optional chaining
         * @param {ASTNode} node node to check
         * @returns {void}
         */
        function checkUnsafeArithmetic(node) {
            checkUndefinedShortCircuit(node, reportUnsafeArithmetic);
        }

        return {
            "AssignmentExpression, AssignmentPattern"(node) {
                if (isDestructuringPattern(node.left)) {
                    checkUnsafeUsage(node.right);
                }
            },
            "ClassDeclaration, ClassExpression"(node) {
                checkUnsafeUsage(node.superClass);
            },
            CallExpression(node) {
                if (!node.optional) {
                    checkUnsafeUsage(node.callee);
                }
            },
            NewExpression(node) {
                checkUnsafeUsage(node.callee);
            },
            VariableDeclarator(node) {
                if (isDestructuringPattern(node.id)) {
                    checkUnsafeUsage(node.init);
                }
            },
            MemberExpression(node) {
                if (!node.optional) {
                    checkUnsafeUsage(node.object);
                }
            },
            TaggedTemplateExpression(node) {
                checkUnsafeUsage(node.tag);
            },
            ForOfStatement(node) {
                checkUnsafeUsage(node.right);
            },
            SpreadElement(node) {
                if (node.parent && node.parent.type !== "ObjectExpression") {
                    checkUnsafeUsage(node.argument);
                }
            },
            BinaryExpression(node) {
                if (UNSAFE_RELATIONAL_OPERATORS.has(node.operator)) {
                    checkUnsafeUsage(node.right);
                }
                if (
                    disallowArithmeticOperators &&
                    UNSAFE_ARITHMETIC_OPERATORS.has(node.operator)
                ) {
                    checkUnsafeArithmetic(node.right);
                    checkUnsafeArithmetic(node.left);
                }
            },
            WithStatement(node) {
                checkUnsafeUsage(node.object);
            },
            UnaryExpression(node) {
                if (
                    disallowArithmeticOperators &&
                    UNSAFE_ARITHMETIC_OPERATORS.has(node.operator)
                ) {
                    checkUnsafeArithmetic(node.argument);
                }
            },
            AssignmentExpression(node) {
                if (
                    disallowArithmeticOperators &&
                    UNSAFE_ASSIGNMENT_OPERATORS.has(node.operator)
                ) {
                    checkUnsafeArithmetic(node.right);
                }
            }
        };
    }
};


code:
/**
 * @fileoverview Flag expressions in statement position that do not side effect
 * @author Michael Ficarra
 */
"use strict";

const astUtils = require("./utils/ast-utils");

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

/**
 * Returns `true`.
 * @returns {boolean} `true`.
 */
function alwaysTrue() {
    return true;
}

/**
 * Returns `false`.
 * @returns {boolean} `false`.
 */
function alwaysFalse() {
    return false;
}

/** @type {import('../shared/types').Rule} */
module.exports = {
    meta: {
        type: "suggestion",

        docs: {
            description: "Disallow unused expressions",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-unused-expressions"
        },

        schema: [
            {
                type: "object",
                properties: {
                    allowShortCircuit: {
                        type: "boolean",
                        default: false
                    },
                    allowTernary: {
                        type: "boolean",
                        default: false
                    },
                    allowTaggedTemplates: {
                        type: "boolean",
                        default: false
                    },
                    enforceForJSX: {
                        type: "boolean",
                        default: false
                    }
                },
                additionalProperties: false
            }
        ],

        messages: {
            unusedExpression: "Expected an assignment or function call and instead saw an expression."
        }
    },

    create(context) {
        const config = context.options[0] || {},
            allowShortCircuit = config.allowShortCircuit || false,
            allowTernary = config.allowTernary || false,
            allowTaggedTemplates = config.allowTaggedTemplates || false,
            enforceForJSX = config.enforceForJSX || false;

        /**
         * Has AST suggesting a directive.
         * @param {ASTNode} node any node
         * @returns {boolean} whether the given node structurally represents a directive
         */
        function looksLikeDirective(node) {
            return node.type === "ExpressionStatement" &&
                node.expression.type === "Literal" && typeof node.expression.value === "string";
        }

        /**
         * Gets the leading sequence of members in a list that pass the predicate.
         * @param {Function} predicate ([a] -> Boolean) the function used to make the determination
         * @param {a[]} list the input list
         * @returns {a[]} the leading sequence of members in the given list that pass the given predicate
         */
        function takeWhile(predicate, list) {
            for (let i = 0; i < list.length; ++i) {
                if (!predicate(list[i])) {
                    return list.slice(0, i);
                }
            }
            return list.slice();
        }

        /**
         * Gets leading directives nodes in a Node body.
         * @param {ASTNode} node a Program or BlockStatement node
         * @returns {ASTNode[]} the leading sequence of directive nodes in the given node's body
         */
        function directives(node) {
            return takeWhile(looksLikeDirective, node.body);
        }

        /**
         * Detect if a Node is a directive.
         * @param {ASTNode} node any node
         * @returns {boolean} whether the given node is considered a directive in its current position
         */
        function isDirective(node) {

            /**
             * https://tc39.es/ecma262/#directive-prologue
             *
             * Only `FunctionBody`, `ScriptBody` and `ModuleBody` can have directive prologue.
             * Class static blocks do not have directive prologue.
             */
            return astUtils.isTopLevelExpressionStatement(node) && directives(node.parent).includes(node);
        }

        /**
         * The member functions return `true` if the type has no side-effects.
         * Unknown nodes are handled as `false`, then this rule ignores those.
         */
        const Checker = Object.assign(Object.create(null), {
            isDisallowed(node) {
                return (Checker[node.type] || alwaysFalse)(node);
            },

            ArrayExpression: alwaysTrue,
            ArrowFunctionExpression: alwaysTrue,
            BinaryExpression: alwaysTrue,
            ChainExpression(node) {
                return Checker.isDisallowed(node.expression);
            },
            ClassExpression: alwaysTrue,
            ConditionalExpression(node) {
                if (allowTernary) {
                    return Checker.isDisallowed(node.consequent) || Checker.isDisallowed(node.alternate);
                }
                return true;
            },
            FunctionExpression: alwaysTrue,
            Identifier: alwaysTrue,
            JSXElement() {
                return enforceForJSX;
            },
            JSXFragment() {
                return enforceForJSX;
            },
            Literal: alwaysTrue,
            LogicalExpression(node) {
                if (allowShortCircuit) {
                    return Checker.isDisallowed(node.right);
                }
                return true;
            },
            MemberExpression: alwaysTrue,
            MetaProperty: alwaysTrue,
            ObjectExpression: alwaysTrue,
            SequenceExpression: alwaysTrue,
            TaggedTemplateExpression() {
                return !allowTaggedTemplates;
            },
            TemplateLiteral: alwaysTrue,
            ThisExpression: alwaysTrue,
            UnaryExpression(node) {
                return node.operator !== "void" && node.operator !== "delete";
            }
        });

        return {
            ExpressionStatement(node) {
                if (Checker.isDisallowed(node.expression) && !isDirective(node)) {
                    context.report({ node, messageId: "unusedExpression" });
                }
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to disallow unused labels.
 * @author Toru Nagashima
 */

"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const astUtils = require("./utils/ast-utils");

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

/** @type {import('../shared/types').Rule} */
module.exports = {
    meta: {
        type: "suggestion",

        docs: {
            description: "Disallow unused labels",
            recommended: true,
            url: "https://eslint.org/docs/latest/rules/no-unused-labels"
        },

        schema: [],

        fixable: "code",

        messages: {
            unused: "'{{name}}:' is defined but never used."
        }
    },

    create(context) {
        const sourceCode = context.sourceCode;
        let scopeInfo = null;

        /**
         * Adds a scope info to the stack.
         * @param {ASTNode} node A node to add. This is a LabeledStatement.
         * @returns {void}
         */
        function enterLabeledScope(node) {
            scopeInfo = {
                label: node.label.name,
                used: false,
                upper: scopeInfo
            };
        }

        /**
         * Checks if a `LabeledStatement` node is fixable.
         * For a node to be fixable, there must be no comments between the label and the body.
         * Furthermore, is must be possible to remove the label without turning the body statement into a
         * directive after other fixes are applied.
         * @param {ASTNode} node The node to evaluate.
         * @returns {boolean} Whether or not the node is fixable.
         */
        function isFixable(node) {

            /*
             * Only perform a fix if there are no comments between the label and the body. This will be the case
             * when there is exactly one token/comment (the ":") between the label and the body.
             */
            if (sourceCode.getTokenAfter(node.label, { includeComments: true }) !==
                sourceCode.getTokenBefore(node.body, { includeComments: true })) {
                return false;
            }

            // Looking for the node's deepest ancestor which is not a `LabeledStatement`.
            let ancestor = node.parent;

            while (ancestor.type === "LabeledStatement") {
                ancestor = ancestor.parent;
            }

            if (ancestor.type === "Program" ||
                (ancestor.type === "BlockStatement" && astUtils.isFunction(ancestor.parent))) {
                const { body } = node;

                if (body.type === "ExpressionStatement" &&
                    ((body.expression.type === "Literal" && typeof body.expression.value === "string") ||
                    astUtils.isStaticTemplateLiteral(body.expression))) {
                    return false; // potential directive
                }
            }
            return true;
        }

        /**
         * Removes the top of the stack.
         * At the same time, this reports the label if it's never used.
         * @param {ASTNode} node A node to report. This is a LabeledStatement.
         * @returns {void}
         */
        function exitLabeledScope(node) {
            if (!scopeInfo.used) {
                context.report({
                    node: node.label,
                    messageId: "unused",
                    data: node.label,
                    fix: isFixable(node) ? fixer => fixer.removeRange([node.range[0], node.body.range[0]]) : null
                });
            }

            scopeInfo = scopeInfo.upper;
        }

        /**
         * Marks the label of a given node as used.
         * @param {ASTNode} node A node to mark. This is a BreakStatement or
         *      ContinueStatement.
         * @returns {void}
         */
        function markAsUsed(node) {
            if (!node.label) {
                return;
            }

            const label = node.label.name;
            let info = scopeInfo;

            while (info) {
                if (info.label === label) {
                    info.used = true;
                    break;
                }
                info = info.upper;
            }
        }

        return {
            LabeledStatement: enterLabeledScope,
            "LabeledStatement:exit": exitLabeledScope,
            BreakStatement: markAsUsed,
            ContinueStatement: markAsUsed
        };
    }
};