code:
/**
 * @fileoverview enforce a particular style for multiline comments
 * @author Teddy Katz
 */
"use strict";

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

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

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

        docs: {
            description: "Enforce a particular style for multiline comments",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/multiline-comment-style"
        },

        fixable: "whitespace",
        schema: {
            anyOf: [
                {
                    type: "array",
                    items: [
                        {
                            enum: ["starred-block", "bare-block"]
                        }
                    ],
                    additionalItems: false
                },
                {
                    type: "array",
                    items: [
                        {
                            enum: ["separate-lines"]
                        },
                        {
                            type: "object",
                            properties: {
                                checkJSDoc: {
                                    type: "boolean"
                                }
                            },
                            additionalProperties: false
                        }
                    ],
                    additionalItems: false
                }
            ]
        },
        messages: {
            expectedBlock: "Expected a block comment instead of consecutive line comments.",
            expectedBareBlock: "Expected a block comment without padding stars.",
            startNewline: "Expected a linebreak after '/*'.",
            endNewline: "Expected a linebreak before '*/'.",
            missingStar: "Expected a '*' at the start of this line.",
            alignment: "Expected this line to be aligned with the start of the comment.",
            expectedLines: "Expected multiple line comments instead of a block comment."
        }
    },

    create(context) {
        const sourceCode = context.sourceCode;
        const option = context.options[0] || "starred-block";
        const params = context.options[1] || {};
        const checkJSDoc = !!params.checkJSDoc;

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

        /**
         * Checks if a comment line is starred.
         * @param {string} line A string representing a comment line.
         * @returns {boolean} Whether or not the comment line is starred.
         */
        function isStarredCommentLine(line) {
            return /^\s*\*/u.test(line);
        }

        /**
         * Checks if a comment group is in starred-block form.
         * @param {Token[]} commentGroup A group of comments, containing either multiple line comments or a single block comment.
         * @returns {boolean} Whether or not the comment group is in starred block form.
         */
        function isStarredBlockComment([firstComment]) {
            if (firstComment.type !== "Block") {
                return false;
            }

            const lines = firstComment.value.split(astUtils.LINEBREAK_MATCHER);

            // The first and last lines can only contain whitespace.
            return lines.length > 0 && lines.every((line, i) => (i === 0 || i === lines.length - 1 ? /^\s*$/u : /^\s*\*/u).test(line));
        }

        /**
         * Checks if a comment group is in JSDoc form.
         * @param {Token[]} commentGroup A group of comments, containing either multiple line comments or a single block comment.
         * @returns {boolean} Whether or not the comment group is in JSDoc form.
         */
        function isJSDocComment([firstComment]) {
            if (firstComment.type !== "Block") {
                return false;
            }

            const lines = firstComment.value.split(astUtils.LINEBREAK_MATCHER);

            return /^\*\s*$/u.test(lines[0]) &&
                lines.slice(1, -1).every(line => /^\s* /u.test(line)) &&
                /^\s*$/u.test(lines[lines.length - 1]);
        }

        /**
         * Processes a comment group that is currently in separate-line form, calculating the offset for each line.
         * @param {Token[]} commentGroup A group of comments containing multiple line comments.
         * @returns {string[]} An array of the processed lines.
         */
        function processSeparateLineComments(commentGroup) {
            const allLinesHaveLeadingSpace = commentGroup
                .map(({ value }) => value)
                .filter(line => line.trim().length)
                .every(line => line.startsWith(" "));

            return commentGroup.map(({ value }) => (allLinesHaveLeadingSpace ? value.replace(/^ /u, "") : value));
        }

        /**
         * Processes a comment group that is currently in starred-block form, calculating the offset for each line.
         * @param {Token} comment A single block comment token in starred-block form.
         * @returns {string[]} An array of the processed lines.
         */
        function processStarredBlockComment(comment) {
            const lines = comment.value.split(astUtils.LINEBREAK_MATCHER)
                .filter((line, i, linesArr) => !(i === 0 || i === linesArr.length - 1))
                .map(line => line.replace(/^\s*$/u, ""));
            const allLinesHaveLeadingSpace = lines
                .map(line => line.replace(/\s*\*/u, ""))
                .filter(line => line.trim().length)
                .every(line => line.startsWith(" "));

            return lines.map(line => line.replace(allLinesHaveLeadingSpace ? /\s*\* ?/u : /\s*\*/u, ""));
        }

        /**
         * Processes a comment group that is currently in bare-block form, calculating the offset for each line.
         * @param {Token} comment A single block comment token in bare-block form.
         * @returns {string[]} An array of the processed lines.
         */
        function processBareBlockComment(comment) {
            const lines = comment.value.split(astUtils.LINEBREAK_MATCHER).map(line => line.replace(/^\s*$/u, ""));
            const leadingWhitespace = `${sourceCode.text.slice(comment.range[0] - comment.loc.start.column, comment.range[0])}   `;
            let offset = "";

            /*
             * Calculate the offset of the least indented line and use that as the basis for offsetting all the lines.
             * The first line should not be checked because it is inline with the opening block comment delimiter.
             */
            for (const [i, line] of lines.entries()) {
                if (!line.trim().length || i === 0) {
                    continue;
                }

                const [, lineOffset] = line.match(/^(\s*\*?\s*)/u);

                if (lineOffset.length < leadingWhitespace.length) {
                    const newOffset = leadingWhitespace.slice(lineOffset.length - leadingWhitespace.length);

                    if (newOffset.length > offset.length) {
                        offset = newOffset;
                    }
                }
            }

            return lines.map(line => {
                const match = line.match(/^(\s*\*?\s*)(.*)/u);
                const [, lineOffset, lineContents] = match;

                if (lineOffset.length > leadingWhitespace.length) {
                    return `${lineOffset.slice(leadingWhitespace.length - (offset.length + lineOffset.length))}${lineContents}`;
                }

                if (lineOffset.length < leadingWhitespace.length) {
                    return `${lineOffset.slice(leadingWhitespace.length)}${lineContents}`;
                }

                return lineContents;
            });
        }

        /**
         * Gets a list of comment lines in a group, formatting leading whitespace as necessary.
         * @param {Token[]} commentGroup A group of comments containing either multiple line comments or a single block comment.
         * @returns {string[]} A list of comment lines.
         */
        function getCommentLines(commentGroup) {
            const [firstComment] = commentGroup;

            if (firstComment.type === "Line") {
                return processSeparateLineComments(commentGroup);
            }

            if (isStarredBlockComment(commentGroup)) {
                return processStarredBlockComment(firstComment);
            }

            return processBareBlockComment(firstComment);
        }

        /**
         * Gets the initial offset (whitespace) from the beginning of a line to a given comment token.
         * @param {Token} comment The token to check.
         * @returns {string} The offset from the beginning of a line to the token.
         */
        function getInitialOffset(comment) {
            return sourceCode.text.slice(comment.range[0] - comment.loc.start.column, comment.range[0]);
        }

        /**
         * Converts a comment into starred-block form
         * @param {Token} firstComment The first comment of the group being converted
         * @param {string[]} commentLinesList A list of lines to appear in the new starred-block comment
         * @returns {string} A representation of the comment value in starred-block form, excluding start and end markers
         */
        function convertToStarredBlock(firstComment, commentLinesList) {
            const initialOffset = getInitialOffset(firstComment);

            return `/*\n${commentLinesList.map(line => `${initialOffset} * ${line}`).join("\n")}\n${initialOffset} */`;
        }

        /**
         * Converts a comment into separate-line form
         * @param {Token} firstComment The first comment of the group being converted
         * @param {string[]} commentLinesList A list of lines to appear in the new starred-block comment
         * @returns {string} A representation of the comment value in separate-line form
         */
        function convertToSeparateLines(firstComment, commentLinesList) {
            return commentLinesList.map(line => `// ${line}`).join(`\n${getInitialOffset(firstComment)}`);
        }

        /**
         * Converts a comment into bare-block form
         * @param {Token} firstComment The first comment of the group being converted
         * @param {string[]} commentLinesList A list of lines to appear in the new starred-block comment
         * @returns {string} A representation of the comment value in bare-block form
         */
        function convertToBlock(firstComment, commentLinesList) {
            return `/* ${commentLinesList.join(`\n${getInitialOffset(firstComment)}   `)} */`;
        }

        /**
         * Each method checks a group of comments to see if it's valid according to the given option.
         * @param {Token[]} commentGroup A list of comments that appear together. This will either contain a single
         * block comment or multiple line comments.
         * @returns {void}
         */
        const commentGroupCheckers = {
            "starred-block"(commentGroup) {
                const [firstComment] = commentGroup;
                const commentLines = getCommentLines(commentGroup);

                if (commentLines.some(value => value.includes("*/"))) {
                    return;
                }

                if (commentGroup.length > 1) {
                    context.report({
                        loc: {
                            start: firstComment.loc.start,
                            end: commentGroup[commentGroup.length - 1].loc.end
                        },
                        messageId: "expectedBlock",
                        fix(fixer) {
                            const range = [firstComment.range[0], commentGroup[commentGroup.length - 1].range[1]];

                            return commentLines.some(value => value.startsWith("/"))
                                ? null
                                : fixer.replaceTextRange(range, convertToStarredBlock(firstComment, commentLines));
                        }
                    });
                } else {
                    const lines = firstComment.value.split(astUtils.LINEBREAK_MATCHER);
                    const expectedLeadingWhitespace = getInitialOffset(firstComment);
                    const expectedLinePrefix = `${expectedLeadingWhitespace} *`;

                    if (!/^\*?\s*$/u.test(lines[0])) {
                        const start = firstComment.value.startsWith("*") ? firstComment.range[0] + 1 : firstComment.range[0];

                        context.report({
                            loc: {
                                start: firstComment.loc.start,
                                end: { line: firstComment.loc.start.line, column: firstComment.loc.start.column + 2 }
                            },
                            messageId: "startNewline",
                            fix: fixer => fixer.insertTextAfterRange([start, start + 2], `\n${expectedLinePrefix}`)
                        });
                    }

                    if (!/^\s*$/u.test(lines[lines.length - 1])) {
                        context.report({
                            loc: {
                                start: { line: firstComment.loc.end.line, column: firstComment.loc.end.column - 2 },
                                end: firstComment.loc.end
                            },
                            messageId: "endNewline",
                            fix: fixer => fixer.replaceTextRange([firstComment.range[1] - 2, firstComment.range[1]], `\n${expectedLinePrefix}/`)
                        });
                    }

                    for (let lineNumber = firstComment.loc.start.line + 1; lineNumber <= firstComment.loc.end.line; lineNumber++) {
                        const lineText = sourceCode.lines[lineNumber - 1];
                        const errorType = isStarredCommentLine(lineText)
                            ? "alignment"
                            : "missingStar";

                        if (!lineText.startsWith(expectedLinePrefix)) {
                            context.report({
                                loc: {
                                    start: { line: lineNumber, column: 0 },
                                    end: { line: lineNumber, column: lineText.length }
                                },
                                messageId: errorType,
                                fix(fixer) {
                                    const lineStartIndex = sourceCode.getIndexFromLoc({ line: lineNumber, column: 0 });

                                    if (errorType === "alignment") {
                                        const [, commentTextPrefix = ""] = lineText.match(/^(\s*\*)/u) || [];
                                        const commentTextStartIndex = lineStartIndex + commentTextPrefix.length;

                                        return fixer.replaceTextRange([lineStartIndex, commentTextStartIndex], expectedLinePrefix);
                                    }

                                    const [, commentTextPrefix = ""] = lineText.match(/^(\s*)/u) || [];
                                    const commentTextStartIndex = lineStartIndex + commentTextPrefix.length;
                                    let offset;

                                    for (const [idx, line] of lines.entries()) {
                                        if (!/\S+/u.test(line)) {
                                            continue;
                                        }

                                        const lineTextToAlignWith = sourceCode.lines[firstComment.loc.start.line - 1 + idx];
                                        const [, prefix = "", initialOffset = ""] = lineTextToAlignWith.match(/^(\s*(?:\/?\*)?(\s*))/u) || [];

                                        offset = `${commentTextPrefix.slice(prefix.length)}${initialOffset}`;

                                        if (/^\s*\//u.test(lineText) && offset.length === 0) {
                                            offset += " ";
                                        }
                                        break;
                                    }

                                    return fixer.replaceTextRange([lineStartIndex, commentTextStartIndex], `${expectedLinePrefix}${offset}`);
                                }
                            });
                        }
                    }
                }
            },
            "separate-lines"(commentGroup) {
                const [firstComment] = commentGroup;

                const isJSDoc = isJSDocComment(commentGroup);

                if (firstComment.type !== "Block" || (!checkJSDoc && isJSDoc)) {
                    return;
                }

                let commentLines = getCommentLines(commentGroup);

                if (isJSDoc) {
                    commentLines = commentLines.slice(1, commentLines.length - 1);
                }

                const tokenAfter = sourceCode.getTokenAfter(firstComment, { includeComments: true });

                if (tokenAfter && firstComment.loc.end.line === tokenAfter.loc.start.line) {
                    return;
                }

                context.report({
                    loc: {
                        start: firstComment.loc.start,
                        end: { line: firstComment.loc.start.line, column: firstComment.loc.start.column + 2 }
                    },
                    messageId: "expectedLines",
                    fix(fixer) {
                        return fixer.replaceText(firstComment, convertToSeparateLines(firstComment, commentLines));
                    }
                });
            },
            "bare-block"(commentGroup) {
                if (isJSDocComment(commentGroup)) {
                    return;
                }

                const [firstComment] = commentGroup;
                const commentLines = getCommentLines(commentGroup);

                // Disallows consecutive line comments in favor of using a block comment.
                if (firstComment.type === "Line" && commentLines.length > 1 &&
                    !commentLines.some(value => value.includes("*/"))) {
                    context.report({
                        loc: {
                            start: firstComment.loc.start,
                            end: commentGroup[commentGroup.length - 1].loc.end
                        },
                        messageId: "expectedBlock",
                        fix(fixer) {
                            return fixer.replaceTextRange(
                                [firstComment.range[0], commentGroup[commentGroup.length - 1].range[1]],
                                convertToBlock(firstComment, commentLines)
                            );
                        }
                    });
                }

                // Prohibits block comments from having a * at the beginning of each line.
                if (isStarredBlockComment(commentGroup)) {
                    context.report({
                        loc: {
                            start: firstComment.loc.start,
                            end: { line: firstComment.loc.start.line, column: firstComment.loc.start.column + 2 }
                        },
                        messageId: "expectedBareBlock",
                        fix(fixer) {
                            return fixer.replaceText(firstComment, convertToBlock(firstComment, commentLines));
                        }
                    });
                }
            }
        };

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

        return {
            Program() {
                return sourceCode.getAllComments()
                    .filter(comment => comment.type !== "Shebang")
                    .filter(comment => !astUtils.COMMENTS_IGNORE_PATTERN.test(comment.value))
                    .filter(comment => {
                        const tokenBefore = sourceCode.getTokenBefore(comment, { includeComments: true });

                        return !tokenBefore || tokenBefore.loc.end.line < comment.loc.start.line;
                    })
                    .reduce((commentGroups, comment, index, commentList) => {
                        const tokenBefore = sourceCode.getTokenBefore(comment, { includeComments: true });

                        if (
                            comment.type === "Line" &&
                            index && commentList[index - 1].type === "Line" &&
                            tokenBefore && tokenBefore.loc.end.line === comment.loc.start.line - 1 &&
                            tokenBefore === commentList[index - 1]
                        ) {
                            commentGroups[commentGroups.length - 1].push(comment);
                        } else {
                            commentGroups.push([comment]);
                        }

                        return commentGroups;
                    }, [])
                    .filter(commentGroup => !(commentGroup.length === 1 && commentGroup[0].loc.start.line === commentGroup[0].loc.end.line))
                    .forEach(commentGroupCheckers[option]);
            }
        };
    }
};


code:
/**
 * @fileoverview Enforce newlines between operands of ternary expressions
 * @author Kai Cataldo
 * @deprecated in ESLint v8.53.0
 */

"use strict";

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

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

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

        docs: {
            description: "Enforce newlines between operands of ternary expressions",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/multiline-ternary"
        },

        schema: [
            {
                enum: ["always", "always-multiline", "never"]
            }
        ],

        messages: {
            expectedTestCons: "Expected newline between test and consequent of ternary expression.",
            expectedConsAlt: "Expected newline between consequent and alternate of ternary expression.",
            unexpectedTestCons: "Unexpected newline between test and consequent of ternary expression.",
            unexpectedConsAlt: "Unexpected newline between consequent and alternate of ternary expression."
        },

        fixable: "whitespace"
    },

    create(context) {
        const sourceCode = context.sourceCode;
        const option = context.options[0];
        const multiline = option !== "never";
        const allowSingleLine = option === "always-multiline";

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

        return {
            ConditionalExpression(node) {
                const questionToken = sourceCode.getTokenAfter(node.test, astUtils.isNotClosingParenToken);
                const colonToken = sourceCode.getTokenAfter(node.consequent, astUtils.isNotClosingParenToken);

                const firstTokenOfTest = sourceCode.getFirstToken(node);
                const lastTokenOfTest = sourceCode.getTokenBefore(questionToken);
                const firstTokenOfConsequent = sourceCode.getTokenAfter(questionToken);
                const lastTokenOfConsequent = sourceCode.getTokenBefore(colonToken);
                const firstTokenOfAlternate = sourceCode.getTokenAfter(colonToken);

                const areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfTest, firstTokenOfConsequent);
                const areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfConsequent, firstTokenOfAlternate);

                const hasComments = !!sourceCode.getCommentsInside(node).length;

                if (!multiline) {
                    if (!areTestAndConsequentOnSameLine) {
                        context.report({
                            node: node.test,
                            loc: {
                                start: firstTokenOfTest.loc.start,
                                end: lastTokenOfTest.loc.end
                            },
                            messageId: "unexpectedTestCons",
                            fix(fixer) {
                                if (hasComments) {
                                    return null;
                                }
                                const fixers = [];
                                const areTestAndQuestionOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfTest, questionToken);
                                const areQuestionAndConsOnSameLine = astUtils.isTokenOnSameLine(questionToken, firstTokenOfConsequent);

                                if (!areTestAndQuestionOnSameLine) {
                                    fixers.push(fixer.removeRange([lastTokenOfTest.range[1], questionToken.range[0]]));
                                }
                                if (!areQuestionAndConsOnSameLine) {
                                    fixers.push(fixer.removeRange([questionToken.range[1], firstTokenOfConsequent.range[0]]));
                                }

                                return fixers;
                            }
                        });
                    }

                    if (!areConsequentAndAlternateOnSameLine) {
                        context.report({
                            node: node.consequent,
                            loc: {
                                start: firstTokenOfConsequent.loc.start,
                                end: lastTokenOfConsequent.loc.end
                            },
                            messageId: "unexpectedConsAlt",
                            fix(fixer) {
                                if (hasComments) {
                                    return null;
                                }
                                const fixers = [];
                                const areConsAndColonOnSameLine = astUtils.isTokenOnSameLine(lastTokenOfConsequent, colonToken);
                                const areColonAndAltOnSameLine = astUtils.isTokenOnSameLine(colonToken, firstTokenOfAlternate);

                                if (!areConsAndColonOnSameLine) {
                                    fixers.push(fixer.removeRange([lastTokenOfConsequent.range[1], colonToken.range[0]]));
                                }
                                if (!areColonAndAltOnSameLine) {
                                    fixers.push(fixer.removeRange([colonToken.range[1], firstTokenOfAlternate.range[0]]));
                                }

                                return fixers;
                            }
                        });
                    }
                } else {
                    if (allowSingleLine && node.loc.start.line === node.loc.end.line) {
                        return;
                    }

                    if (areTestAndConsequentOnSameLine) {
                        context.report({
                            node: node.test,
                            loc: {
                                start: firstTokenOfTest.loc.start,
                                end: lastTokenOfTest.loc.end
                            },
                            messageId: "expectedTestCons",
                            fix: fixer => (hasComments ? null : (
                                fixer.replaceTextRange(
                                    [
                                        lastTokenOfTest.range[1],
                                        questionToken.range[0]
                                    ],
                                    "\n"
                                )
                            ))
                        });
                    }

                    if (areConsequentAndAlternateOnSameLine) {
                        context.report({
                            node: node.consequent,
                            loc: {
                                start: firstTokenOfConsequent.loc.start,
                                end: lastTokenOfConsequent.loc.end
                            },
                            messageId: "expectedConsAlt",
                            fix: (fixer => (hasComments ? null : (
                                fixer.replaceTextRange(
                                    [
                                        lastTokenOfConsequent.range[1],
                                        colonToken.range[0]
                                    ],
                                    "\n"
                                )
                            )))
                        });
                    }
                }
            }
        };
    }
};

license: mit


code:
/**
 * @fileoverview Rule to flag use of constructors without capital letters
 * @author Nicholas C. Zakas
 */

"use strict";

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

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

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

const CAPS_ALLOWED = [
    "Array",
    "Boolean",
    "Date",
    "Error",
    "Function",
    "Number",
    "Object",
    "RegExp",
    "String",
    "Symbol",
    "BigInt"
];

/**
 * Ensure that if the key is provided, it must be an array.
 * @param {Object} obj Object to check with `key`.
 * @param {string} key Object key to check on `obj`.
 * @param {any} fallback If obj[key] is not present, this will be returned.
 * @throws {TypeError} If key is not an own array type property of `obj`.
 * @returns {string[]} Returns obj[key] if it's an Array, otherwise `fallback`
 */
function checkArray(obj, key, fallback) {

    /* c8 ignore start */
    if (Object.prototype.hasOwnProperty.call(obj, key) && !Array.isArray(obj[key])) {
        throw new TypeError(`${key}, if provided, must be an Array`);
    }/* c8 ignore stop */
    return obj[key] || fallback;
}

/**
 * A reducer function to invert an array to an Object mapping the string form of the key, to `true`.
 * @param {Object} map Accumulator object for the reduce.
 * @param {string} key Object key to set to `true`.
 * @returns {Object} Returns the updated Object for further reduction.
 */
function invert(map, key) {
    map[key] = true;
    return map;
}

/**
 * Creates an object with the cap is new exceptions as its keys and true as their values.
 * @param {Object} config Rule configuration
 * @returns {Object} Object with cap is new exceptions.
 */
function calculateCapIsNewExceptions(config) {
    let capIsNewExceptions = checkArray(config, "capIsNewExceptions", CAPS_ALLOWED);

    if (capIsNewExceptions !== CAPS_ALLOWED) {
        capIsNewExceptions = capIsNewExceptions.concat(CAPS_ALLOWED);
    }

    return capIsNewExceptions.reduce(invert, {});
}

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

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

        docs: {
            description: "Require constructor names to begin with a capital letter",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/new-cap"
        },

        schema: [
            {
                type: "object",
                properties: {
                    newIsCap: {
                        type: "boolean",
                        default: true
                    },
                    capIsNew: {
                        type: "boolean",
                        default: true
                    },
                    newIsCapExceptions: {
                        type: "array",
                        items: {
                            type: "string"
                        }
                    },
                    newIsCapExceptionPattern: {
                        type: "string"
                    },
                    capIsNewExceptions: {
                        type: "array",
                        items: {
                            type: "string"
                        }
                    },
                    capIsNewExceptionPattern: {
                        type: "string"
                    },
                    properties: {
                        type: "boolean",
                        default: true
                    }
                },
                additionalProperties: false
            }
        ],
        messages: {
            upper: "A function with a name starting with an uppercase letter should only be used as a constructor.",
            lower: "A constructor name should not start with a lowercase letter."
        }
    },

    create(context) {

        const config = Object.assign({}, context.options[0]);

        config.newIsCap = config.newIsCap !== false;
        config.capIsNew = config.capIsNew !== false;
        const skipProperties = config.properties === false;

        const newIsCapExceptions = checkArray(config, "newIsCapExceptions", []).reduce(invert, {});
        const newIsCapExceptionPattern = config.newIsCapExceptionPattern ? new RegExp(config.newIsCapExceptionPattern, "u") : null;

        const capIsNewExceptions = calculateCapIsNewExceptions(config);
        const capIsNewExceptionPattern = config.capIsNewExceptionPattern ? new RegExp(config.capIsNewExceptionPattern, "u") : null;

        const listeners = {};

        const sourceCode = context.sourceCode;

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

        /**
         * Get exact callee name from expression
         * @param {ASTNode} node CallExpression or NewExpression node
         * @returns {string} name
         */
        function extractNameFromExpression(node) {
            return node.callee.type === "Identifier"
                ? node.callee.name
                : astUtils.getStaticPropertyName(node.callee) || "";
        }

        /**
         * Returns the capitalization state of the string -
         * Whether the first character is uppercase, lowercase, or non-alphabetic
         * @param {string} str String
         * @returns {string} capitalization state: "non-alpha", "lower", or "upper"
         */
        function getCap(str) {
            const firstChar = str.charAt(0);

            const firstCharLower = firstChar.toLowerCase();
            const firstCharUpper = firstChar.toUpperCase();

            if (firstCharLower === firstCharUpper) {

                // char has no uppercase variant, so it's non-alphabetic
                return "non-alpha";
            }
            if (firstChar === firstCharLower) {
                return "lower";
            }
            return "upper";

        }

        /**
         * Check if capitalization is allowed for a CallExpression
         * @param {Object} allowedMap Object mapping calleeName to a Boolean
         * @param {ASTNode} node CallExpression node
         * @param {string} calleeName Capitalized callee name from a CallExpression
         * @param {Object} pattern RegExp object from options pattern
         * @returns {boolean} Returns true if the callee may be capitalized
         */
        function isCapAllowed(allowedMap, node, calleeName, pattern) {
            const sourceText = sourceCode.getText(node.callee);

            if (allowedMap[calleeName] || allowedMap[sourceText]) {
                return true;
            }

            if (pattern && pattern.test(sourceText)) {
                return true;
            }

            const callee = astUtils.skipChainExpression(node.callee);

            if (calleeName === "UTC" && callee.type === "MemberExpression") {

                // allow if callee is Date.UTC
                return callee.object.type === "Identifier" &&
                    callee.object.name === "Date";
            }

            return skipProperties && callee.type === "MemberExpression";
        }

        /**
         * Reports the given messageId for the given node. The location will be the start of the property or the callee.
         * @param {ASTNode} node CallExpression or NewExpression node.
         * @param {string} messageId The messageId to report.
         * @returns {void}
         */
        function report(node, messageId) {
            let callee = astUtils.skipChainExpression(node.callee);

            if (callee.type === "MemberExpression") {
                callee = callee.property;
            }

            context.report({ node, loc: callee.loc, messageId });
        }

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

        if (config.newIsCap) {
            listeners.NewExpression = function(node) {

                const constructorName = extractNameFromExpression(node);

                if (constructorName) {
                    const capitalization = getCap(constructorName);
                    const isAllowed = capitalization !== "lower" || isCapAllowed(newIsCapExceptions, node, constructorName, newIsCapExceptionPattern);

                    if (!isAllowed) {
                        report(node, "lower");
                    }
                }
            };
        }

        if (config.capIsNew) {
            listeners.CallExpression = function(node) {

                const calleeName = extractNameFromExpression(node);

                if (calleeName) {
                    const capitalization = getCap(calleeName);
                    const isAllowed = capitalization !== "upper" || isCapAllowed(capIsNewExceptions, node, calleeName, capIsNewExceptionPattern);

                    if (!isAllowed) {
                        report(node, "upper");
                    }
                }
            };
        }

        return listeners;
    }
};


code:
/**
 * @fileoverview Rule to flag when using constructor without parentheses
 * @author Ilya Volodin
 * @deprecated in ESLint v8.53.0
 */

"use strict";

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

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

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

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

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

        docs: {
            description: "Enforce or disallow parentheses when invoking a constructor with no arguments",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/new-parens"
        },

        fixable: "code",
        schema: [
            {
                enum: ["always", "never"]
            }
        ],
        messages: {
            missing: "Missing '()' invoking a constructor.",
            unnecessary: "Unnecessary '()' invoking a constructor with no arguments."
        }
    },

    create(context) {
        const options = context.options;
        const always = options[0] !== "never"; // Default is always

        const sourceCode = context.sourceCode;

        return {
            NewExpression(node) {
                if (node.arguments.length !== 0) {
                    return; // if there are arguments, there have to be parens
                }

                const lastToken = sourceCode.getLastToken(node);
                const hasLastParen = lastToken && astUtils.isClosingParenToken(lastToken);

                // `hasParens` is true only if the new expression ends with its own parens, e.g., new new foo() does not end with its own parens
                const hasParens = hasLastParen &&
                    astUtils.isOpeningParenToken(sourceCode.getTokenBefore(lastToken)) &&
                    node.callee.range[1] < node.range[1];

                if (always) {
                    if (!hasParens) {
                        context.report({
                            node,
                            messageId: "missing",
                            fix: fixer => fixer.insertTextAfter(node, "()")
                        });
                    }
                } else {
                    if (hasParens) {
                        context.report({
                            node,
                            messageId: "unnecessary",
                            fix: fixer => [
                                fixer.remove(sourceCode.getTokenBefore(lastToken)),
                                fixer.remove(lastToken),
                                fixer.insertTextBefore(node, "("),
                                fixer.insertTextAfter(node, ")")
                            ]
                        });
                    }
                }
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to check empty newline after "var" statement
 * @author Gopal Venkatesan
 * @deprecated in ESLint v4.0.0
 */

"use strict";

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

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

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

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

        docs: {
            description: "Require or disallow an empty line after variable declarations",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/newline-after-var"
        },
        schema: [
            {
                enum: ["never", "always"]
            }
        ],
        fixable: "whitespace",
        messages: {
            expected: "Expected blank line after variable declarations.",
            unexpected: "Unexpected blank line after variable declarations."
        },

        deprecated: true,

        replacedBy: ["padding-line-between-statements"]
    },

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

        // Default `mode` to "always".
        const mode = context.options[0] === "never" ? "never" : "always";

        // Cache starting and ending line numbers of comments for faster lookup
        const commentEndLine = sourceCode.getAllComments().reduce((result, token) => {
            result[token.loc.start.line] = token.loc.end.line;
            return result;
        }, {});

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

        /**
         * Gets a token from the given node to compare line to the next statement.
         *
         * In general, the token is the last token of the node. However, the token is the second last token if the following conditions satisfy.
         *
         * - The last token is semicolon.
         * - The semicolon is on a different line from the previous token of the semicolon.
         *
         * This behavior would address semicolon-less style code. e.g.:
         *
         *     var foo = 1
         *
         *     ;(a || b).doSomething()
         * @param {ASTNode} node The node to get.
         * @returns {Token} The token to compare line to the next statement.
         */
        function getLastToken(node) {
            const lastToken = sourceCode.getLastToken(node);

            if (lastToken.type === "Punctuator" && lastToken.value === ";") {
                const prevToken = sourceCode.getTokenBefore(lastToken);

                if (prevToken.loc.end.line !== lastToken.loc.start.line) {
                    return prevToken;
                }
            }

            return lastToken;
        }

        /**
         * Determine if provided keyword is a variable declaration
         * @private
         * @param {string} keyword keyword to test
         * @returns {boolean} True if `keyword` is a type of var
         */
        function isVar(keyword) {
            return keyword === "var" || keyword === "let" || keyword === "const";
        }

        /**
         * Determine if provided keyword is a variant of for specifiers
         * @private
         * @param {string} keyword keyword to test
         * @returns {boolean} True if `keyword` is a variant of for specifier
         */
        function isForTypeSpecifier(keyword) {
            return keyword === "ForStatement" || keyword === "ForInStatement" || keyword === "ForOfStatement";
        }

        /**
         * Determine if provided keyword is an export specifiers
         * @private
         * @param {string} nodeType nodeType to test
         * @returns {boolean} True if `nodeType` is an export specifier
         */
        function isExportSpecifier(nodeType) {
            return nodeType === "ExportNamedDeclaration" || nodeType === "ExportSpecifier" ||
                nodeType === "ExportDefaultDeclaration" || nodeType === "ExportAllDeclaration";
        }

        /**
         * Determine if provided node is the last of their parent block.
         * @private
         * @param {ASTNode} node node to test
         * @returns {boolean} True if `node` is last of their parent block.
         */
        function isLastNode(node) {
            const token = sourceCode.getTokenAfter(node);

            return !token || (token.type === "Punctuator" && token.value === "}");
        }

        /**
         * Gets the last line of a group of consecutive comments
         * @param {number} commentStartLine The starting line of the group
         * @returns {number} The number of the last comment line of the group
         */
        function getLastCommentLineOfBlock(commentStartLine) {
            const currentCommentEnd = commentEndLine[commentStartLine];

            return commentEndLine[currentCommentEnd + 1] ? getLastCommentLineOfBlock(currentCommentEnd + 1) : currentCommentEnd;
        }

        /**
         * Determine if a token starts more than one line after a comment ends
         * @param {token} token The token being checked
         * @param {integer} commentStartLine The line number on which the comment starts
         * @returns {boolean} True if `token` does not start immediately after a comment
         */
        function hasBlankLineAfterComment(token, commentStartLine) {
            return token.loc.start.line > getLastCommentLineOfBlock(commentStartLine) + 1;
        }

        /**
         * Checks that a blank line exists after a variable declaration when mode is
         * set to "always", or checks that there is no blank line when mode is set
         * to "never"
         * @private
         * @param {ASTNode} node `VariableDeclaration` node to test
         * @returns {void}
         */
        function checkForBlankLine(node) {

            /*
             * lastToken is the last token on the node's line. It will usually also be the last token of the node, but it will
             * sometimes be second-last if there is a semicolon on a different line.
             */
            const lastToken = getLastToken(node),

                /*
                 * If lastToken is the last token of the node, nextToken should be the token after the node. Otherwise, nextToken
                 * is the last token of the node.
                 */
                nextToken = lastToken === sourceCode.getLastToken(node) ? sourceCode.getTokenAfter(node) : sourceCode.getLastToken(node),
                nextLineNum = lastToken.loc.end.line + 1;

            // Ignore if there is no following statement
            if (!nextToken) {
                return;
            }

            // Ignore if parent of node is a for variant
            if (isForTypeSpecifier(node.parent.type)) {
                return;
            }

            // Ignore if parent of node is an export specifier
            if (isExportSpecifier(node.parent.type)) {
                return;
            }

            /*
             * Some coding styles use multiple `var` statements, so do nothing if
             * the next token is a `var` statement.
             */
            if (nextToken.type === "Keyword" && isVar(nextToken.value)) {
                return;
            }

            // Ignore if it is last statement in a block
            if (isLastNode(node)) {
                return;
            }

            // Next statement is not a `var`...
            const noNextLineToken = nextToken.loc.start.line > nextLineNum;
            const hasNextLineComment = (typeof commentEndLine[nextLineNum] !== "undefined");

            if (mode === "never" && noNextLineToken && !hasNextLineComment) {
                context.report({
                    node,
                    messageId: "unexpected",
                    fix(fixer) {
                        const linesBetween = sourceCode.getText().slice(lastToken.range[1], nextToken.range[0]).split(astUtils.LINEBREAK_MATCHER);

                        return fixer.replaceTextRange([lastToken.range[1], nextToken.range[0]], `${linesBetween.slice(0, -1).join("")}\n${linesBetween[linesBetween.length - 1]}`);
                    }
                });
            }

            // Token on the next line, or comment without blank line
            if (
                mode === "always" && (
                    !noNextLineToken ||
                    hasNextLineComment && !hasBlankLineAfterComment(nextToken, nextLineNum)
                )
            ) {
                context.report({
                    node,
                    messageId: "expected",
                    fix(fixer) {
                        if ((noNextLineToken ? getLastCommentLineOfBlock(nextLineNum) : lastToken.loc.end.line) === nextToken.loc.start.line) {
                            return fixer.insertTextBefore(nextToken, "\n\n");
                        }

                        return fixer.insertTextBeforeRange([nextToken.range[0] - nextToken.loc.start.column, nextToken.range[1]], "\n");
                    }
                });
            }
        }

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

        return {
            VariableDeclaration: checkForBlankLine
        };

    }
};


code:
/**
 * @fileoverview Rule to require newlines before `return` statement
 * @author Kai Cataldo
 * @deprecated in ESLint v4.0.0
 */
"use strict";

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

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

        docs: {
            description: "Require an empty line before `return` statements",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/newline-before-return"
        },

        fixable: "whitespace",
        schema: [],
        messages: {
            expected: "Expected newline before return statement."
        },

        deprecated: true,
        replacedBy: ["padding-line-between-statements"]
    },

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

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

        /**
         * Tests whether node is preceded by supplied tokens
         * @param {ASTNode} node node to check
         * @param {Array} testTokens array of tokens to test against
         * @returns {boolean} Whether or not the node is preceded by one of the supplied tokens
         * @private
         */
        function isPrecededByTokens(node, testTokens) {
            const tokenBefore = sourceCode.getTokenBefore(node);

            return testTokens.includes(tokenBefore.value);
        }

        /**
         * Checks whether node is the first node after statement or in block
         * @param {ASTNode} node node to check
         * @returns {boolean} Whether or not the node is the first node after statement or in block
         * @private
         */
        function isFirstNode(node) {
            const parentType = node.parent.type;

            if (node.parent.body) {
                return Array.isArray(node.parent.body)
                    ? node.parent.body[0] === node
                    : node.parent.body === node;
            }

            if (parentType === "IfStatement") {
                return isPrecededByTokens(node, ["else", ")"]);
            }
            if (parentType === "DoWhileStatement") {
                return isPrecededByTokens(node, ["do"]);
            }
            if (parentType === "SwitchCase") {
                return isPrecededByTokens(node, [":"]);
            }
            return isPrecededByTokens(node, [")"]);

        }

        /**
         * Returns the number of lines of comments that precede the node
         * @param {ASTNode} node node to check for overlapping comments
         * @param {number} lineNumTokenBefore line number of previous token, to check for overlapping comments
         * @returns {number} Number of lines of comments that precede the node
         * @private
         */
        function calcCommentLines(node, lineNumTokenBefore) {
            const comments = sourceCode.getCommentsBefore(node);
            let numLinesComments = 0;

            if (!comments.length) {
                return numLinesComments;
            }

            comments.forEach(comment => {
                numLinesComments++;

                if (comment.type === "Block") {
                    numLinesComments += comment.loc.end.line - comment.loc.start.line;
                }

                // avoid counting lines with inline comments twice
                if (comment.loc.start.line === lineNumTokenBefore) {
                    numLinesComments--;
                }

                if (comment.loc.end.line === node.loc.start.line) {
                    numLinesComments--;
                }
            });

            return numLinesComments;
        }

        /**
         * Returns the line number of the token before the node that is passed in as an argument
         * @param {ASTNode} node The node to use as the start of the calculation
         * @returns {number} Line number of the token before `node`
         * @private
         */
        function getLineNumberOfTokenBefore(node) {
            const tokenBefore = sourceCode.getTokenBefore(node);
            let lineNumTokenBefore;

            /**
             * Global return (at the beginning of a script) is a special case.
             * If there is no token before `return`, then we expect no line
             * break before the return. Comments are allowed to occupy lines
             * before the global return, just no blank lines.
             * Setting lineNumTokenBefore to zero in that case results in the
             * desired behavior.
             */
            if (tokenBefore) {
                lineNumTokenBefore = tokenBefore.loc.end.line;
            } else {
                lineNumTokenBefore = 0; // global return at beginning of script
            }

            return lineNumTokenBefore;
        }

        /**
         * Checks whether node is preceded by a newline
         * @param {ASTNode} node node to check
         * @returns {boolean} Whether or not the node is preceded by a newline
         * @private
         */
        function hasNewlineBefore(node) {
            const lineNumNode = node.loc.start.line;
            const lineNumTokenBefore = getLineNumberOfTokenBefore(node);
            const commentLines = calcCommentLines(node, lineNumTokenBefore);

            return (lineNumNode - lineNumTokenBefore - commentLines) > 1;
        }

        /**
         * Checks whether it is safe to apply a fix to a given return statement.
         *
         * The fix is not considered safe if the given return statement has leading comments,
         * as we cannot safely determine if the newline should be added before or after the comments.
         * For more information, see: https://github.com/eslint/eslint/issues/5958#issuecomment-222767211
         * @param {ASTNode} node The return statement node to check.
         * @returns {boolean} `true` if it can fix the node.
         * @private
         */
        function canFix(node) {
            const leadingComments = sourceCode.getCommentsBefore(node);
            const lastLeadingComment = leadingComments[leadingComments.length - 1];
            const tokenBefore = sourceCode.getTokenBefore(node);

            if (leadingComments.length === 0) {
                return true;
            }

            /*
             * if the last leading comment ends in the same line as the previous token and
             * does not share a line with the `return` node, we can consider it safe to fix.
             * Example:
             * function a() {
             *     var b; //comment
             *     return;
             * }
             */
            if (lastLeadingComment.loc.end.line === tokenBefore.loc.end.line &&
                lastLeadingComment.loc.end.line !== node.loc.start.line) {
                return true;
            }

            return false;
        }

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

        return {
            ReturnStatement(node) {
                if (!isFirstNode(node) && !hasNewlineBefore(node)) {
                    context.report({
                        node,
                        messageId: "expected",
                        fix(fixer) {
                            if (canFix(node)) {
                                const tokenBefore = sourceCode.getTokenBefore(node);
                                const newlines = node.loc.start.line === tokenBefore.loc.end.line ? "\n\n" : "\n";

                                return fixer.insertTextBefore(node, newlines);
                            }
                            return null;
                        }
                    });
                }
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to ensure newline per method call when chaining calls
 * @author Rajendra Patil
 * @author Burak Yigit Kaya
 * @deprecated in ESLint v8.53.0
 */

"use strict";

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

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

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

        docs: {
            description: "Require a newline after each call in a method chain",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/newline-per-chained-call"
        },

        fixable: "whitespace",

        schema: [{
            type: "object",
            properties: {
                ignoreChainWithDepth: {
                    type: "integer",
                    minimum: 1,
                    maximum: 10,
                    default: 2
                }
            },
            additionalProperties: false
        }],
        messages: {
            expected: "Expected line break before `{{callee}}`."
        }
    },

    create(context) {

        const options = context.options[0] || {},
            ignoreChainWithDepth = options.ignoreChainWithDepth || 2;

        const sourceCode = context.sourceCode;

        /**
         * Get the prefix of a given MemberExpression node.
         * If the MemberExpression node is a computed value it returns a
         * left bracket. If not it returns a period.
         * @param {ASTNode} node A MemberExpression node to get
         * @returns {string} The prefix of the node.
         */
        function getPrefix(node) {
            if (node.computed) {
                if (node.optional) {
                    return "?.[";
                }
                return "[";
            }
            if (node.optional) {
                return "?.";
            }
            return ".";
        }

        /**
         * Gets the property text of a given MemberExpression node.
         * If the text is multiline, this returns only the first line.
         * @param {ASTNode} node A MemberExpression node to get.
         * @returns {string} The property text of the node.
         */
        function getPropertyText(node) {
            const prefix = getPrefix(node);
            const lines = sourceCode.getText(node.property).split(astUtils.LINEBREAK_MATCHER);
            const suffix = node.computed && lines.length === 1 ? "]" : "";

            return prefix + lines[0] + suffix;
        }

        return {
            "CallExpression:exit"(node) {
                const callee = astUtils.skipChainExpression(node.callee);

                if (callee.type !== "MemberExpression") {
                    return;
                }

                let parent = astUtils.skipChainExpression(callee.object);
                let depth = 1;

                while (parent && parent.callee) {
                    depth += 1;
                    parent = astUtils.skipChainExpression(astUtils.skipChainExpression(parent.callee).object);
                }

                if (depth > ignoreChainWithDepth && astUtils.isTokenOnSameLine(callee.object, callee.property)) {
                    const firstTokenAfterObject = sourceCode.getTokenAfter(callee.object, astUtils.isNotClosingParenToken);

                    context.report({
                        node: callee.property,
                        loc: {
                            start: firstTokenAfterObject.loc.start,
                            end: callee.loc.end
                        },
                        messageId: "expected",
                        data: {
                            callee: getPropertyText(callee)
                        },
                        fix(fixer) {
                            return fixer.insertTextBefore(firstTokenAfterObject, "\n");
                        }
                    });
                }
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to flag use of alert, confirm, prompt
 * @author Nicholas C. Zakas
 */
"use strict";

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

const {
    getStaticPropertyName: getPropertyName,
    getVariableByName,
    skipChainExpression
} = require("./utils/ast-utils");

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

/**
 * Checks if the given name is a prohibited identifier.
 * @param {string} name The name to check
 * @returns {boolean} Whether or not the name is prohibited.
 */
function isProhibitedIdentifier(name) {
    return /^(alert|confirm|prompt)$/u.test(name);
}

/**
 * Finds the eslint-scope reference in the given scope.
 * @param {Object} scope The scope to search.
 * @param {ASTNode} node The identifier node.
 * @returns {Reference|null} Returns the found reference or null if none were found.
 */
function findReference(scope, node) {
    const references = scope.references.filter(reference => reference.identifier.range[0] === node.range[0] &&
            reference.identifier.range[1] === node.range[1]);

    if (references.length === 1) {
        return references[0];
    }
    return null;
}

/**
 * Checks if the given identifier node is shadowed in the given scope.
 * @param {Object} scope The current scope.
 * @param {string} node The identifier node to check
 * @returns {boolean} Whether or not the name is shadowed.
 */
function isShadowed(scope, node) {
    const reference = findReference(scope, node);

    return reference && reference.resolved && reference.resolved.defs.length > 0;
}

/**
 * Checks if the given identifier node is a ThisExpression in the global scope or the global window property.
 * @param {Object} scope The current scope.
 * @param {string} node The identifier node to check
 * @returns {boolean} Whether or not the node is a reference to the global object.
 */
function isGlobalThisReferenceOrGlobalWindow(scope, node) {
    if (scope.type === "global" && node.type === "ThisExpression") {
        return true;
    }
    if (
        node.type === "Identifier" &&
        (
            node.name === "window" ||
            (node.name === "globalThis" && getVariableByName(scope, "globalThis"))
        )
    ) {
        return !isShadowed(scope, node);
    }

    return false;
}

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

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

        docs: {
            description: "Disallow the use of `alert`, `confirm`, and `prompt`",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-alert"
        },

        schema: [],

        messages: {
            unexpected: "Unexpected {{name}}."
        }
    },

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

        return {
            CallExpression(node) {
                const callee = skipChainExpression(node.callee),
                    currentScope = sourceCode.getScope(node);

                // without window.
                if (callee.type === "Identifier") {
                    const name = callee.name;

                    if (!isShadowed(currentScope, callee) && isProhibitedIdentifier(callee.name)) {
                        context.report({
                            node,
                            messageId: "unexpected",
                            data: { name }
                        });
                    }

                } else if (callee.type === "MemberExpression" && isGlobalThisReferenceOrGlobalWindow(currentScope, callee.object)) {
                    const name = getPropertyName(callee);

                    if (isProhibitedIdentifier(name)) {
                        context.report({
                            node,
                            messageId: "unexpected",
                            data: { name }
                        });
                    }
                }
            }
        };

    }
};


code:
/**
 * @fileoverview Disallow construction of dense arrays using the Array constructor
 * @author Matt DuVall <http://www.mattduvall.com/>
 */

"use strict";

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

const {
    getVariableByName,
    isClosingParenToken,
    isOpeningParenToken,
    isStartOfExpressionStatement,
    needsPrecedingSemicolon
} = require("./utils/ast-utils");

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

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

        docs: {
            description: "Disallow `Array` constructors",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-array-constructor"
        },

        hasSuggestions: true,

        schema: [],

        messages: {
            preferLiteral: "The array literal notation [] is preferable.",
            useLiteral: "Replace with an array literal.",
            useLiteralAfterSemicolon: "Replace with an array literal, add preceding semicolon."
        }
    },

    create(context) {

        const sourceCode = context.sourceCode;

        /**
         * Gets the text between the calling parentheses of a CallExpression or NewExpression.
         * @param {ASTNode} node A CallExpression or NewExpression node.
         * @returns {string} The text between the calling parentheses, or an empty string if there are none.
         */
        function getArgumentsText(node) {
            const lastToken = sourceCode.getLastToken(node);

            if (!isClosingParenToken(lastToken)) {
                return "";
            }

            let firstToken = node.callee;

            do {
                firstToken = sourceCode.getTokenAfter(firstToken);
                if (!firstToken || firstToken === lastToken) {
                    return "";
                }
            } while (!isOpeningParenToken(firstToken));

            return sourceCode.text.slice(firstToken.range[1], lastToken.range[0]);
        }

        /**
         * Disallow construction of dense arrays using the Array constructor
         * @param {ASTNode} node node to evaluate
         * @returns {void}
         * @private
         */
        function check(node) {
            if (
                node.callee.type !== "Identifier" ||
                node.callee.name !== "Array" ||
                node.arguments.length === 1 &&
                node.arguments[0].type !== "SpreadElement") {
                return;
            }

            const variable = getVariableByName(sourceCode.getScope(node), "Array");

            /*
             * Check if `Array` is a predefined global variable: predefined globals have no declarations,
             * meaning that the `identifiers` list of the variable object is empty.
             */
            if (variable && variable.identifiers.length === 0) {
                const argsText = getArgumentsText(node);
                let fixText;
                let messageId;

                /*
                 * Check if the suggested change should include a preceding semicolon or not.
                 * Due to JavaScript's ASI rules, a missing semicolon may be inserted automatically
                 * before an expression like `Array()` or `new Array()`, but not when the expression
                 * is changed into an array literal like `[]`.
                 */
                if (isStartOfExpressionStatement(node) && needsPrecedingSemicolon(sourceCode, node)) {
                    fixText = `;[${argsText}]`;
                    messageId = "useLiteralAfterSemicolon";
                } else {
                    fixText = `[${argsText}]`;
                    messageId = "useLiteral";
                }

                context.report({
                    node,
                    messageId: "preferLiteral",
                    suggest: [
                        {
                            messageId,
                            fix: fixer => fixer.replaceText(node, fixText)
                        }
                    ]
                });
            }
        }

        return {
            CallExpression: check,
            NewExpression: check
        };

    }
};


code:
/**
 * @fileoverview disallow using an async function as a Promise executor
 * @author Teddy Katz
 */
"use strict";

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

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

        docs: {
            description: "Disallow using an async function as a Promise executor",
            recommended: true,
            url: "https://eslint.org/docs/latest/rules/no-async-promise-executor"
        },

        fixable: null,
        schema: [],
        messages: {
            async: "Promise executor functions should not be async."
        }
    },

    create(context) {
        return {
            "NewExpression[callee.name='Promise'][arguments.0.async=true]"(node) {
                context.report({
                    node: context.sourceCode.getFirstToken(node.arguments[0], token => token.value === "async"),
                    messageId: "async"
                });
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to disallow uses of await inside of loops.
 * @author Nat Mote (nmote)
 */
"use strict";

/**
 * Check whether it should stop traversing ancestors at the given node.
 * @param {ASTNode} node A node to check.
 * @returns {boolean} `true` if it should stop traversing.
 */
function isBoundary(node) {
    const t = node.type;

    return (
        t === "FunctionDeclaration" ||
        t === "FunctionExpression" ||
        t === "ArrowFunctionExpression" ||

        /*
         * Don't report the await expressions on for-await-of loop since it's
         * asynchronous iteration intentionally.
         */
        (t === "ForOfStatement" && node.await === true)
    );
}

/**
 * Check whether the given node is in loop.
 * @param {ASTNode} node A node to check.
 * @param {ASTNode} parent A parent node to check.
 * @returns {boolean} `true` if the node is in loop.
 */
function isLooped(node, parent) {
    switch (parent.type) {
        case "ForStatement":
            return (
                node === parent.test ||
                node === parent.update ||
                node === parent.body
            );

        case "ForOfStatement":
        case "ForInStatement":
            return node === parent.body;

        case "WhileStatement":
        case "DoWhileStatement":
            return node === parent.test || node === parent.body;

        default:
            return false;
    }
}

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

        docs: {
            description: "Disallow `await` inside of loops",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-await-in-loop"
        },

        schema: [],

        messages: {
            unexpectedAwait: "Unexpected `await` inside a loop."
        }
    },
    create(context) {

        /**
         * Validate an await expression.
         * @param {ASTNode} awaitNode An AwaitExpression or ForOfStatement node to validate.
         * @returns {void}
         */
        function validate(awaitNode) {
            if (awaitNode.type === "ForOfStatement" && !awaitNode.await) {
                return;
            }

            let node = awaitNode;
            let parent = node.parent;

            while (parent && !isBoundary(parent)) {
                if (isLooped(node, parent)) {
                    context.report({
                        node: awaitNode,
                        messageId: "unexpectedAwait"
                    });
                    return;
                }
                node = parent;
                parent = parent.parent;
            }
        }

        return {
            AwaitExpression: validate,
            ForOfStatement: validate
        };
    }
};


code:
/**
 * @fileoverview Rule to flag bitwise identifiers
 * @author Nicholas C. Zakas
 */

"use strict";

/*
 *
 * Set of bitwise operators.
 *
 */
const BITWISE_OPERATORS = [
    "^", "|", "&", "<<", ">>", ">>>",
    "^=", "|=", "&=", "<<=", ">>=", ">>>=",
    "~"
];

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

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

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

        schema: [
            {
                type: "object",
                properties: {
                    allow: {
                        type: "array",
                        items: {
                            enum: BITWISE_OPERATORS
                        },
                        uniqueItems: true
                    },
                    int32Hint: {
                        type: "boolean",
                        default: false
                    }
                },
                additionalProperties: false
            }
        ],

        messages: {
            unexpected: "Unexpected use of '{{operator}}'."
        }
    },

    create(context) {
        const options = context.options[0] || {};
        const allowed = options.allow || [];
        const int32Hint = options.int32Hint === true;

        /**
         * Reports an unexpected use of a bitwise operator.
         * @param {ASTNode} node Node which contains the bitwise operator.
         * @returns {void}
         */
        function report(node) {
            context.report({ node, messageId: "unexpected", data: { operator: node.operator } });
        }

        /**
         * Checks if the given node has a bitwise operator.
         * @param {ASTNode} node The node to check.
         * @returns {boolean} Whether or not the node has a bitwise operator.
         */
        function hasBitwiseOperator(node) {
            return BITWISE_OPERATORS.includes(node.operator);
        }

        /**
         * Checks if exceptions were provided, e.g. `{ allow: ['~', '|'] }`.
         * @param {ASTNode} node The node to check.
         * @returns {boolean} Whether or not the node has a bitwise operator.
         */
        function allowedOperator(node) {
            return allowed.includes(node.operator);
        }

        /**
         * Checks if the given bitwise operator is used for integer typecasting, i.e. "|0"
         * @param {ASTNode} node The node to check.
         * @returns {boolean} whether the node is used in integer typecasting.
         */
        function isInt32Hint(node) {
            return int32Hint && node.operator === "|" && node.right &&
              node.right.type === "Literal" && node.right.value === 0;
        }

        /**
         * Report if the given node contains a bitwise operator.
         * @param {ASTNode} node The node to check.
         * @returns {void}
         */
        function checkNodeForBitwiseOperator(node) {
            if (hasBitwiseOperator(node) && !allowedOperator(node) && !isInt32Hint(node)) {
                report(node);
            }
        }

        return {
            AssignmentExpression: checkNodeForBitwiseOperator,
            BinaryExpression: checkNodeForBitwiseOperator,
            UnaryExpression: checkNodeForBitwiseOperator
        };

    }
};


code:
/**
 * @fileoverview disallow use of the Buffer() constructor
 * @author Teddy Katz
 * @deprecated in ESLint v7.0.0
 */
"use strict";

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

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

        replacedBy: [],

        type: "problem",

        docs: {
            description: "Disallow use of the `Buffer()` constructor",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-buffer-constructor"
        },

        schema: [],

        messages: {
            deprecated: "{{expr}} is deprecated. Use Buffer.from(), Buffer.alloc(), or Buffer.allocUnsafe() instead."
        }
    },

    create(context) {

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

        return {
            "CallExpression[callee.name='Buffer'], NewExpression[callee.name='Buffer']"(node) {
                context.report({
                    node,
                    messageId: "deprecated",
                    data: { expr: node.type === "CallExpression" ? "Buffer()" : "new Buffer()" }
                });
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to flag use of arguments.callee and arguments.caller.
 * @author Nicholas C. Zakas
 */

"use strict";

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

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

        docs: {
            description: "Disallow the use of `arguments.caller` or `arguments.callee`",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-caller"
        },

        schema: [],

        messages: {
            unexpected: "Avoid arguments.{{prop}}."
        }
    },

    create(context) {

        return {

            MemberExpression(node) {
                const objectName = node.object.name,
                    propertyName = node.property.name;

                if (objectName === "arguments" && !node.computed && propertyName && propertyName.match(/^calle[er]$/u)) {
                    context.report({ node, messageId: "unexpected", data: { prop: propertyName } });
                }

            }
        };

    }
};


code:
/**
 * @fileoverview Rule to flag use of an lexical declarations inside a case clause
 * @author Erik Arvidsson
 */
"use strict";

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

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

        docs: {
            description: "Disallow lexical declarations in case clauses",
            recommended: true,
            url: "https://eslint.org/docs/latest/rules/no-case-declarations"
        },

        schema: [],

        messages: {
            unexpected: "Unexpected lexical declaration in case block."
        }
    },

    create(context) {

        /**
         * Checks whether or not a node is a lexical declaration.
         * @param {ASTNode} node A direct child statement of a switch case.
         * @returns {boolean} Whether or not the node is a lexical declaration.
         */
        function isLexicalDeclaration(node) {
            switch (node.type) {
                case "FunctionDeclaration":
                case "ClassDeclaration":
                    return true;
                case "VariableDeclaration":
                    return node.kind !== "var";
                default:
                    return false;
            }
        }

        return {
            SwitchCase(node) {
                for (let i = 0; i < node.consequent.length; i++) {
                    const statement = node.consequent[i];

                    if (isLexicalDeclaration(statement)) {
                        context.report({
                            node: statement,
                            messageId: "unexpected"
                        });
                    }
                }
            }
        };

    }
};


code:
/**
 * @fileoverview A rule to disallow modifying variables of class declarations
 * @author Toru Nagashima
 */

"use strict";

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

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

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

        docs: {
            description: "Disallow reassigning class members",
            recommended: true,
            url: "https://eslint.org/docs/latest/rules/no-class-assign"
        },

        schema: [],

        messages: {
            class: "'{{name}}' is a class."
        }
    },

    create(context) {

        const sourceCode = context.sourceCode;

        /**
         * Finds and reports references that are non initializer and writable.
         * @param {Variable} variable A variable to check.
         * @returns {void}
         */
        function checkVariable(variable) {
            astUtils.getModifyingReferences(variable.references).forEach(reference => {
                context.report({ node: reference.identifier, messageId: "class", data: { name: reference.identifier.name } });

            });
        }

        /**
         * Finds and reports references that are non initializer and writable.
         * @param {ASTNode} node A ClassDeclaration/ClassExpression node to check.
         * @returns {void}
         */
        function checkForClass(node) {
            sourceCode.getDeclaredVariables(node).forEach(checkVariable);
        }

        return {
            ClassDeclaration: checkForClass,
            ClassExpression: checkForClass
        };

    }
};


code:
/**
 * @fileoverview The rule should warn against code that tries to compare against -0.
 * @author Aladdin-ADD <hh_2013@foxmail.com>
 */
"use strict";

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

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

        docs: {
            description: "Disallow comparing against -0",
            recommended: true,
            url: "https://eslint.org/docs/latest/rules/no-compare-neg-zero"
        },

        fixable: null,
        schema: [],

        messages: {
            unexpected: "Do not use the '{{operator}}' operator to compare against -0."
        }
    },

    create(context) {

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

        /**
         * Checks a given node is -0
         * @param {ASTNode} node A node to check.
         * @returns {boolean} `true` if the node is -0.
         */
        function isNegZero(node) {
            return node.type === "UnaryExpression" && node.operator === "-" && node.argument.type === "Literal" && node.argument.value === 0;
        }
        const OPERATORS_TO_CHECK = new Set([">", ">=", "<", "<=", "==", "===", "!=", "!=="]);

        return {
            BinaryExpression(node) {
                if (OPERATORS_TO_CHECK.has(node.operator)) {
                    if (isNegZero(node.left) || isNegZero(node.right)) {
                        context.report({
                            node,
                            messageId: "unexpected",
                            data: { operator: node.operator }
                        });
                    }
                }
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to flag assignment in a conditional statement's test expression
 * @author Stephen Murray <spmurrayzzz>
 */

"use strict";

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

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

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

const TEST_CONDITION_PARENT_TYPES = new Set(["IfStatement", "WhileStatement", "DoWhileStatement", "ForStatement", "ConditionalExpression"]);

const NODE_DESCRIPTIONS = {
    DoWhileStatement: "a 'do...while' statement",
    ForStatement: "a 'for' statement",
    IfStatement: "an 'if' statement",
    WhileStatement: "a 'while' statement"
};

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

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

        docs: {
            description: "Disallow assignment operators in conditional expressions",
            recommended: true,
            url: "https://eslint.org/docs/latest/rules/no-cond-assign"
        },

        schema: [
            {
                enum: ["except-parens", "always"]
            }
        ],

        messages: {
            unexpected: "Unexpected assignment within {{type}}.",

            // must match JSHint's error message
            missing: "Expected a conditional expression and instead saw an assignment."
        }
    },

    create(context) {

        const prohibitAssign = (context.options[0] || "except-parens");

        const sourceCode = context.sourceCode;

        /**
         * Check whether an AST node is the test expression for a conditional statement.
         * @param {!Object} node The node to test.
         * @returns {boolean} `true` if the node is the text expression for a conditional statement; otherwise, `false`.
         */
        function isConditionalTestExpression(node) {
            return node.parent &&
                TEST_CONDITION_PARENT_TYPES.has(node.parent.type) &&
                node === node.parent.test;
        }

        /**
         * Given an AST node, perform a bottom-up search for the first ancestor that represents a conditional statement.
         * @param {!Object} node The node to use at the start of the search.
         * @returns {?Object} The closest ancestor node that represents a conditional statement.
         */
        function findConditionalAncestor(node) {
            let currentAncestor = node;

            do {
                if (isConditionalTestExpression(currentAncestor)) {
                    return currentAncestor.parent;
                }
            } while ((currentAncestor = currentAncestor.parent) && !astUtils.isFunction(currentAncestor));

            return null;
        }

        /**
         * Check whether the code represented by an AST node is enclosed in two sets of parentheses.
         * @param {!Object} node The node to test.
         * @returns {boolean} `true` if the code is enclosed in two sets of parentheses; otherwise, `false`.
         */
        function isParenthesisedTwice(node) {
            const previousToken = sourceCode.getTokenBefore(node, 1),
                nextToken = sourceCode.getTokenAfter(node, 1);

            return astUtils.isParenthesised(sourceCode, node) &&
                previousToken && astUtils.isOpeningParenToken(previousToken) && previousToken.range[1] <= node.range[0] &&
                astUtils.isClosingParenToken(nextToken) && nextToken.range[0] >= node.range[1];
        }

        /**
         * Check a conditional statement's test expression for top-level assignments that are not enclosed in parentheses.
         * @param {!Object} node The node for the conditional statement.
         * @returns {void}
         */
        function testForAssign(node) {
            if (node.test &&
                (node.test.type === "AssignmentExpression") &&
                (node.type === "ForStatement"
                    ? !astUtils.isParenthesised(sourceCode, node.test)
                    : !isParenthesisedTwice(node.test)
                )
            ) {

                context.report({
                    node: node.test,
                    messageId: "missing"
                });
            }
        }

        /**
         * Check whether an assignment expression is descended from a conditional statement's test expression.
         * @param {!Object} node The node for the assignment expression.
         * @returns {void}
         */
        function testForConditionalAncestor(node) {
            const ancestor = findConditionalAncestor(node);

            if (ancestor) {
                context.report({
                    node,
                    messageId: "unexpected",
                    data: {
                        type: NODE_DESCRIPTIONS[ancestor.type] || ancestor.type
                    }
                });
            }
        }

        if (prohibitAssign === "always") {
            return {
                AssignmentExpression: testForConditionalAncestor
            };
        }

        return {
            DoWhileStatement: testForAssign,
            ForStatement: testForAssign,
            IfStatement: testForAssign,
            WhileStatement: testForAssign,
            ConditionalExpression: testForAssign
        };

    }
};


code:
/**
 * @fileoverview A rule to warn against using arrow functions when they could be
 * confused with comparisons
 * @author Jxck <https://github.com/Jxck>
 * @deprecated in ESLint v8.53.0
 */

"use strict";

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

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

/**
 * Checks whether or not a node is a conditional expression.
 * @param {ASTNode} node node to test
 * @returns {boolean} `true` if the node is a conditional expression.
 */
function isConditional(node) {
    return node && node.type === "ConditionalExpression";
}

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

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

        docs: {
            description: "Disallow arrow functions where they could be confused with comparisons",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-confusing-arrow"
        },

        fixable: "code",

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

        messages: {
            confusing: "Arrow function used ambiguously with a conditional expression."
        }
    },

    create(context) {
        const config = context.options[0] || {};
        const allowParens = config.allowParens || (config.allowParens === void 0);
        const onlyOneSimpleParam = config.onlyOneSimpleParam;
        const sourceCode = context.sourceCode;

        /**
         * Reports if an arrow function contains an ambiguous conditional.
         * @param {ASTNode} node A node to check and report.
         * @returns {void}
         */
        function checkArrowFunc(node) {
            const body = node.body;

            if (isConditional(body) &&
                !(allowParens && astUtils.isParenthesised(sourceCode, body)) &&
                !(onlyOneSimpleParam && !(node.params.length === 1 && node.params[0].type === "Identifier"))) {
                context.report({
                    node,
                    messageId: "confusing",
                    fix(fixer) {

                        // if `allowParens` is not set to true don't bother wrapping in parens
                        return allowParens && fixer.replaceText(node.body, `(${sourceCode.getText(node.body)})`);
                    }
                });
            }
        }

        return {
            ArrowFunctionExpression: checkArrowFunc
        };
    }
};