code:
/**
 * @fileoverview Restrict usage of specified node imports.
 * @author Guy Ellis
 */
"use strict";

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

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

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

const ignore = require("ignore");

const arrayOfStringsOrObjects = {
    type: "array",
    items: {
        anyOf: [
            { type: "string" },
            {
                type: "object",
                properties: {
                    name: { type: "string" },
                    message: {
                        type: "string",
                        minLength: 1
                    },
                    importNames: {
                        type: "array",
                        items: {
                            type: "string"
                        }
                    }
                },
                additionalProperties: false,
                required: ["name"]
            }
        ]
    },
    uniqueItems: true
};

const arrayOfStringsOrObjectPatterns = {
    anyOf: [
        {
            type: "array",
            items: {
                type: "string"
            },
            uniqueItems: true
        },
        {
            type: "array",
            items: {
                type: "object",
                properties: {
                    importNames: {
                        type: "array",
                        items: {
                            type: "string"
                        },
                        minItems: 1,
                        uniqueItems: true
                    },
                    group: {
                        type: "array",
                        items: {
                            type: "string"
                        },
                        minItems: 1,
                        uniqueItems: true
                    },
                    importNamePattern: {
                        type: "string"
                    },
                    message: {
                        type: "string",
                        minLength: 1
                    },
                    caseSensitive: {
                        type: "boolean"
                    }
                },
                additionalProperties: false,
                required: ["group"]
            },
            uniqueItems: true
        }
    ]
};

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

        docs: {
            description: "Disallow specified modules when loaded by `import`",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-restricted-imports"
        },

        messages: {
            path: "'{{importSource}}' import is restricted from being used.",
            // eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
            pathWithCustomMessage: "'{{importSource}}' import is restricted from being used. {{customMessage}}",

            patterns: "'{{importSource}}' import is restricted from being used by a pattern.",
            // eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
            patternWithCustomMessage: "'{{importSource}}' import is restricted from being used by a pattern. {{customMessage}}",

            patternAndImportName: "'{{importName}}' import from '{{importSource}}' is restricted from being used by a pattern.",
            // eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
            patternAndImportNameWithCustomMessage: "'{{importName}}' import from '{{importSource}}' is restricted from being used by a pattern. {{customMessage}}",

            patternAndEverything: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted from being used by a pattern.",

            patternAndEverythingWithRegexImportName: "* import is invalid because import name matching '{{importNames}}' pattern from '{{importSource}}' is restricted from being used.",
            // eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
            patternAndEverythingWithCustomMessage: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted from being used by a pattern. {{customMessage}}",
            // eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
            patternAndEverythingWithRegexImportNameAndCustomMessage: "* import is invalid because import name matching '{{importNames}}' pattern from '{{importSource}}' is restricted from being used. {{customMessage}}",

            everything: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted.",
            // eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
            everythingWithCustomMessage: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted. {{customMessage}}",

            importName: "'{{importName}}' import from '{{importSource}}' is restricted.",
            // eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
            importNameWithCustomMessage: "'{{importName}}' import from '{{importSource}}' is restricted. {{customMessage}}"
        },

        schema: {
            anyOf: [
                arrayOfStringsOrObjects,
                {
                    type: "array",
                    items: [{
                        type: "object",
                        properties: {
                            paths: arrayOfStringsOrObjects,
                            patterns: arrayOfStringsOrObjectPatterns
                        },
                        additionalProperties: false
                    }],
                    additionalItems: false
                }
            ]
        }
    },

    create(context) {
        const sourceCode = context.sourceCode;
        const options = Array.isArray(context.options) ? context.options : [];
        const isPathAndPatternsObject =
            typeof options[0] === "object" &&
            (Object.prototype.hasOwnProperty.call(options[0], "paths") || Object.prototype.hasOwnProperty.call(options[0], "patterns"));

        const restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || [];
        const restrictedPathMessages = restrictedPaths.reduce((memo, importSource) => {
            if (typeof importSource === "string") {
                memo[importSource] = { message: null };
            } else {
                memo[importSource.name] = {
                    message: importSource.message,
                    importNames: importSource.importNames
                };
            }
            return memo;
        }, {});

        // Handle patterns too, either as strings or groups
        let restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];

        // standardize to array of objects if we have an array of strings
        if (restrictedPatterns.length > 0 && typeof restrictedPatterns[0] === "string") {
            restrictedPatterns = [{ group: restrictedPatterns }];
        }

        // relative paths are supported for this rule
        const restrictedPatternGroups = restrictedPatterns.map(({ group, message, caseSensitive, importNames, importNamePattern }) => ({
            matcher: ignore({ allowRelativePaths: true, ignorecase: !caseSensitive }).add(group),
            customMessage: message,
            importNames,
            importNamePattern
        }));

        // if no imports are restricted we don't need to check
        if (Object.keys(restrictedPaths).length === 0 && restrictedPatternGroups.length === 0) {
            return {};
        }

        /**
         * Report a restricted path.
         * @param {string} importSource path of the import
         * @param {Map<string,Object[]>} importNames Map of import names that are being imported
         * @param {node} node representing the restricted path reference
         * @returns {void}
         * @private
         */
        function checkRestrictedPathAndReport(importSource, importNames, node) {
            if (!Object.prototype.hasOwnProperty.call(restrictedPathMessages, importSource)) {
                return;
            }

            const customMessage = restrictedPathMessages[importSource].message;
            const restrictedImportNames = restrictedPathMessages[importSource].importNames;

            if (restrictedImportNames) {
                if (importNames.has("*")) {
                    const specifierData = importNames.get("*")[0];

                    context.report({
                        node,
                        messageId: customMessage ? "everythingWithCustomMessage" : "everything",
                        loc: specifierData.loc,
                        data: {
                            importSource,
                            importNames: restrictedImportNames,
                            customMessage
                        }
                    });
                }

                restrictedImportNames.forEach(importName => {
                    if (importNames.has(importName)) {
                        const specifiers = importNames.get(importName);

                        specifiers.forEach(specifier => {
                            context.report({
                                node,
                                messageId: customMessage ? "importNameWithCustomMessage" : "importName",
                                loc: specifier.loc,
                                data: {
                                    importSource,
                                    customMessage,
                                    importName
                                }
                            });
                        });
                    }
                });
            } else {
                context.report({
                    node,
                    messageId: customMessage ? "pathWithCustomMessage" : "path",
                    data: {
                        importSource,
                        customMessage
                    }
                });
            }
        }

        /**
         * Report a restricted path specifically for patterns.
         * @param {node} node representing the restricted path reference
         * @param {Object} group contains an Ignore instance for paths, the customMessage to show on failure,
         * and any restricted import names that have been specified in the config
         * @param {Map<string,Object[]>} importNames Map of import names that are being imported
         * @returns {void}
         * @private
         */
        function reportPathForPatterns(node, group, importNames) {
            const importSource = node.source.value.trim();

            const customMessage = group.customMessage;
            const restrictedImportNames = group.importNames;
            const restrictedImportNamePattern = group.importNamePattern ? new RegExp(group.importNamePattern, "u") : null;

            /*
             * If we are not restricting to any specific import names and just the pattern itself,
             * report the error and move on
             */
            if (!restrictedImportNames && !restrictedImportNamePattern) {
                context.report({
                    node,
                    messageId: customMessage ? "patternWithCustomMessage" : "patterns",
                    data: {
                        importSource,
                        customMessage
                    }
                });
                return;
            }

            importNames.forEach((specifiers, importName) => {
                if (importName === "*") {
                    const [specifier] = specifiers;

                    if (restrictedImportNames) {
                        context.report({
                            node,
                            messageId: customMessage ? "patternAndEverythingWithCustomMessage" : "patternAndEverything",
                            loc: specifier.loc,
                            data: {
                                importSource,
                                importNames: restrictedImportNames,
                                customMessage
                            }
                        });
                    } else {
                        context.report({
                            node,
                            messageId: customMessage ? "patternAndEverythingWithRegexImportNameAndCustomMessage" : "patternAndEverythingWithRegexImportName",
                            loc: specifier.loc,
                            data: {
                                importSource,
                                importNames: restrictedImportNamePattern,
                                customMessage
                            }
                        });
                    }

                    return;
                }

                if (
                    (restrictedImportNames && restrictedImportNames.includes(importName)) ||
                    (restrictedImportNamePattern && restrictedImportNamePattern.test(importName))
                ) {
                    specifiers.forEach(specifier => {
                        context.report({
                            node,
                            messageId: customMessage ? "patternAndImportNameWithCustomMessage" : "patternAndImportName",
                            loc: specifier.loc,
                            data: {
                                importSource,
                                customMessage,
                                importName
                            }
                        });
                    });
                }
            });
        }

        /**
         * Check if the given importSource is restricted by a pattern.
         * @param {string} importSource path of the import
         * @param {Object} group contains a Ignore instance for paths, and the customMessage to show if it fails
         * @returns {boolean} whether the variable is a restricted pattern or not
         * @private
         */
        function isRestrictedPattern(importSource, group) {
            return group.matcher.ignores(importSource);
        }

        /**
         * Checks a node to see if any problems should be reported.
         * @param {ASTNode} node The node to check.
         * @returns {void}
         * @private
         */
        function checkNode(node) {
            const importSource = node.source.value.trim();
            const importNames = new Map();

            if (node.type === "ExportAllDeclaration") {
                const starToken = sourceCode.getFirstToken(node, 1);

                importNames.set("*", [{ loc: starToken.loc }]);
            } else if (node.specifiers) {
                for (const specifier of node.specifiers) {
                    let name;
                    const specifierData = { loc: specifier.loc };

                    if (specifier.type === "ImportDefaultSpecifier") {
                        name = "default";
                    } else if (specifier.type === "ImportNamespaceSpecifier") {
                        name = "*";
                    } else if (specifier.imported) {
                        name = astUtils.getModuleExportName(specifier.imported);
                    } else if (specifier.local) {
                        name = astUtils.getModuleExportName(specifier.local);
                    }

                    if (typeof name === "string") {
                        if (importNames.has(name)) {
                            importNames.get(name).push(specifierData);
                        } else {
                            importNames.set(name, [specifierData]);
                        }
                    }
                }
            }

            checkRestrictedPathAndReport(importSource, importNames, node);
            restrictedPatternGroups.forEach(group => {
                if (isRestrictedPattern(importSource, group)) {
                    reportPathForPatterns(node, group, importNames);
                }
            });
        }

        return {
            ImportDeclaration: checkNode,
            ExportNamedDeclaration(node) {
                if (node.source) {
                    checkNode(node);
                }
            },
            ExportAllDeclaration: checkNode
        };
    }
};


code:
/**
 * @fileoverview Restrict usage of specified node modules.
 * @author Christian Schulz
 * @deprecated in ESLint v7.0.0
 */
"use strict";

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

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

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

const ignore = require("ignore");

const arrayOfStrings = {
    type: "array",
    items: { type: "string" },
    uniqueItems: true
};

const arrayOfStringsOrObjects = {
    type: "array",
    items: {
        anyOf: [
            { type: "string" },
            {
                type: "object",
                properties: {
                    name: { type: "string" },
                    message: {
                        type: "string",
                        minLength: 1
                    }
                },
                additionalProperties: false,
                required: ["name"]
            }
        ]
    },
    uniqueItems: true
};

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

        replacedBy: [],

        type: "suggestion",

        docs: {
            description: "Disallow specified modules when loaded by `require`",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-restricted-modules"
        },

        schema: {
            anyOf: [
                arrayOfStringsOrObjects,
                {
                    type: "array",
                    items: {
                        type: "object",
                        properties: {
                            paths: arrayOfStringsOrObjects,
                            patterns: arrayOfStrings
                        },
                        additionalProperties: false
                    },
                    additionalItems: false
                }
            ]
        },

        messages: {
            defaultMessage: "'{{name}}' module is restricted from being used.",
            // eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
            customMessage: "'{{name}}' module is restricted from being used. {{customMessage}}",
            patternMessage: "'{{name}}' module is restricted from being used by a pattern."
        }
    },

    create(context) {
        const options = Array.isArray(context.options) ? context.options : [];
        const isPathAndPatternsObject =
            typeof options[0] === "object" &&
            (Object.prototype.hasOwnProperty.call(options[0], "paths") || Object.prototype.hasOwnProperty.call(options[0], "patterns"));

        const restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || [];
        const restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];

        const restrictedPathMessages = restrictedPaths.reduce((memo, importName) => {
            if (typeof importName === "string") {
                memo[importName] = null;
            } else {
                memo[importName.name] = importName.message;
            }
            return memo;
        }, {});

        // if no imports are restricted we don't need to check
        if (Object.keys(restrictedPaths).length === 0 && restrictedPatterns.length === 0) {
            return {};
        }

        // relative paths are supported for this rule
        const ig = ignore({ allowRelativePaths: true }).add(restrictedPatterns);

        /**
         * Function to check if a node is a string literal.
         * @param {ASTNode} node The node to check.
         * @returns {boolean} If the node is a string literal.
         */
        function isStringLiteral(node) {
            return node && node.type === "Literal" && typeof node.value === "string";
        }

        /**
         * Function to check if a node is a require call.
         * @param {ASTNode} node The node to check.
         * @returns {boolean} If the node is a require call.
         */
        function isRequireCall(node) {
            return node.callee.type === "Identifier" && node.callee.name === "require";
        }

        /**
         * Extract string from Literal or TemplateLiteral node
         * @param {ASTNode} node The node to extract from
         * @returns {string|null} Extracted string or null if node doesn't represent a string
         */
        function getFirstArgumentString(node) {
            if (isStringLiteral(node)) {
                return node.value.trim();
            }

            if (astUtils.isStaticTemplateLiteral(node)) {
                return node.quasis[0].value.cooked.trim();
            }

            return null;
        }

        /**
         * Report a restricted path.
         * @param {node} node representing the restricted path reference
         * @param {string} name restricted path
         * @returns {void}
         * @private
         */
        function reportPath(node, name) {
            const customMessage = restrictedPathMessages[name];
            const messageId = customMessage
                ? "customMessage"
                : "defaultMessage";

            context.report({
                node,
                messageId,
                data: {
                    name,
                    customMessage
                }
            });
        }

        /**
         * Check if the given name is a restricted path name
         * @param {string} name name of a variable
         * @returns {boolean} whether the variable is a restricted path or not
         * @private
         */
        function isRestrictedPath(name) {
            return Object.prototype.hasOwnProperty.call(restrictedPathMessages, name);
        }

        return {
            CallExpression(node) {
                if (isRequireCall(node)) {

                    // node has arguments
                    if (node.arguments.length) {
                        const name = getFirstArgumentString(node.arguments[0]);

                        // if first argument is a string literal or a static string template literal
                        if (name) {

                            // check if argument value is in restricted modules array
                            if (isRestrictedPath(name)) {
                                reportPath(node, name);
                            }

                            if (restrictedPatterns.length > 0 && ig.ignores(name)) {
                                context.report({
                                    node,
                                    messageId: "patternMessage",
                                    data: { name }
                                });
                            }
                        }
                    }
                }
            }
        };
    }
};

license: mit


code:
/**
 * @fileoverview Rule to disallow certain object properties
 * @author Will Klein & Eli White
 */

"use strict";

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

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

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

        docs: {
            description: "Disallow certain properties on certain objects",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-restricted-properties"
        },

        schema: {
            type: "array",
            items: {
                anyOf: [ // `object` and `property` are both optional, but at least one of them must be provided.
                    {
                        type: "object",
                        properties: {
                            object: {
                                type: "string"
                            },
                            property: {
                                type: "string"
                            },
                            message: {
                                type: "string"
                            }
                        },
                        additionalProperties: false,
                        required: ["object"]
                    },
                    {
                        type: "object",
                        properties: {
                            object: {
                                type: "string"
                            },
                            property: {
                                type: "string"
                            },
                            message: {
                                type: "string"
                            }
                        },
                        additionalProperties: false,
                        required: ["property"]
                    }
                ]
            },
            uniqueItems: true
        },

        messages: {
            // eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
            restrictedObjectProperty: "'{{objectName}}.{{propertyName}}' is restricted from being used.{{message}}",
            // eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
            restrictedProperty: "'{{propertyName}}' is restricted from being used.{{message}}"
        }
    },

    create(context) {
        const restrictedCalls = context.options;

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

        const restrictedProperties = new Map();
        const globallyRestrictedObjects = new Map();
        const globallyRestrictedProperties = new Map();

        restrictedCalls.forEach(option => {
            const objectName = option.object;
            const propertyName = option.property;

            if (typeof objectName === "undefined") {
                globallyRestrictedProperties.set(propertyName, { message: option.message });
            } else if (typeof propertyName === "undefined") {
                globallyRestrictedObjects.set(objectName, { message: option.message });
            } else {
                if (!restrictedProperties.has(objectName)) {
                    restrictedProperties.set(objectName, new Map());
                }

                restrictedProperties.get(objectName).set(propertyName, {
                    message: option.message
                });
            }
        });

        /**
         * Checks to see whether a property access is restricted, and reports it if so.
         * @param {ASTNode} node The node to report
         * @param {string} objectName The name of the object
         * @param {string} propertyName The name of the property
         * @returns {undefined}
         */
        function checkPropertyAccess(node, objectName, propertyName) {
            if (propertyName === null) {
                return;
            }
            const matchedObject = restrictedProperties.get(objectName);
            const matchedObjectProperty = matchedObject ? matchedObject.get(propertyName) : globallyRestrictedObjects.get(objectName);
            const globalMatchedProperty = globallyRestrictedProperties.get(propertyName);

            if (matchedObjectProperty) {
                const message = matchedObjectProperty.message ? ` ${matchedObjectProperty.message}` : "";

                context.report({
                    node,
                    messageId: "restrictedObjectProperty",
                    data: {
                        objectName,
                        propertyName,
                        message
                    }
                });
            } else if (globalMatchedProperty) {
                const message = globalMatchedProperty.message ? ` ${globalMatchedProperty.message}` : "";

                context.report({
                    node,
                    messageId: "restrictedProperty",
                    data: {
                        propertyName,
                        message
                    }
                });
            }
        }

        return {
            MemberExpression(node) {
                checkPropertyAccess(node, node.object && node.object.name, astUtils.getStaticPropertyName(node));
            },
            ObjectPattern(node) {
                let objectName = null;

                if (node.parent.type === "VariableDeclarator") {
                    if (node.parent.init && node.parent.init.type === "Identifier") {
                        objectName = node.parent.init.name;
                    }
                } else if (node.parent.type === "AssignmentExpression" || node.parent.type === "AssignmentPattern") {
                    if (node.parent.right.type === "Identifier") {
                        objectName = node.parent.right.name;
                    }
                }

                node.properties.forEach(property => {
                    checkPropertyAccess(node, objectName, astUtils.getStaticPropertyName(property));
                });
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to flag use of certain node types
 * @author Burak Yigit Kaya
 */
"use strict";

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

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

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

        schema: {
            type: "array",
            items: {
                oneOf: [
                    {
                        type: "string"
                    },
                    {
                        type: "object",
                        properties: {
                            selector: { type: "string" },
                            message: { type: "string" }
                        },
                        required: ["selector"],
                        additionalProperties: false
                    }
                ]
            },
            uniqueItems: true,
            minItems: 0
        },

        messages: {
            // eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
            restrictedSyntax: "{{message}}"
        }
    },

    create(context) {
        return context.options.reduce((result, selectorOrObject) => {
            const isStringFormat = (typeof selectorOrObject === "string");
            const hasCustomMessage = !isStringFormat && Boolean(selectorOrObject.message);

            const selector = isStringFormat ? selectorOrObject : selectorOrObject.selector;
            const message = hasCustomMessage ? selectorOrObject.message : `Using '${selector}' is not allowed.`;

            return Object.assign(result, {
                [selector](node) {
                    context.report({
                        node,
                        messageId: "restrictedSyntax",
                        data: { message }
                    });
                }
            });
        }, {});

    }
};


code:
/**
 * @fileoverview Rule to flag when return statement contains assignment
 * @author Ilya Volodin
 */
"use strict";

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

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

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

const SENTINEL_TYPE = /^(?:[a-zA-Z]+?Statement|ArrowFunctionExpression|FunctionExpression|ClassExpression)$/u;

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

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

        docs: {
            description: "Disallow assignment operators in `return` statements",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-return-assign"
        },

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

        messages: {
            returnAssignment: "Return statement should not contain assignment.",
            arrowAssignment: "Arrow function should not return assignment."
        }
    },

    create(context) {
        const always = (context.options[0] || "except-parens") !== "except-parens";
        const sourceCode = context.sourceCode;

        return {
            AssignmentExpression(node) {
                if (!always && astUtils.isParenthesised(sourceCode, node)) {
                    return;
                }

                let currentChild = node;
                let parent = currentChild.parent;

                // Find ReturnStatement or ArrowFunctionExpression in ancestors.
                while (parent && !SENTINEL_TYPE.test(parent.type)) {
                    currentChild = parent;
                    parent = parent.parent;
                }

                // Reports.
                if (parent && parent.type === "ReturnStatement") {
                    context.report({
                        node: parent,
                        messageId: "returnAssignment"
                    });
                } else if (parent && parent.type === "ArrowFunctionExpression" && parent.body === currentChild) {
                    context.report({
                        node: parent,
                        messageId: "arrowAssignment"
                    });
                }
            }
        };
    }
};


code:
/**
 * @fileoverview Disallows unnecessary `return await`
 * @author Jordan Harband
 * @deprecated in ESLint v8.46.0
 */
"use strict";

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

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

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

        docs: {
            description: "Disallow unnecessary `return await`",

            recommended: false,

            url: "https://eslint.org/docs/latest/rules/no-return-await"
        },

        fixable: null,

        deprecated: true,

        replacedBy: [],

        schema: [
        ],

        messages: {
            removeAwait: "Remove redundant `await`.",
            redundantUseOfAwait: "Redundant use of `await` on a return value."
        }
    },

    create(context) {

        /**
         * Reports a found unnecessary `await` expression.
         * @param {ASTNode} node The node representing the `await` expression to report
         * @returns {void}
         */
        function reportUnnecessaryAwait(node) {
            context.report({
                node: context.sourceCode.getFirstToken(node),
                loc: node.loc,
                messageId: "redundantUseOfAwait",
                suggest: [
                    {
                        messageId: "removeAwait",
                        fix(fixer) {
                            const sourceCode = context.sourceCode;
                            const [awaitToken, tokenAfterAwait] = sourceCode.getFirstTokens(node, 2);

                            const areAwaitAndAwaitedExpressionOnTheSameLine = awaitToken.loc.start.line === tokenAfterAwait.loc.start.line;

                            if (!areAwaitAndAwaitedExpressionOnTheSameLine) {
                                return null;
                            }

                            const [startOfAwait, endOfAwait] = awaitToken.range;

                            const characterAfterAwait = sourceCode.text[endOfAwait];
                            const trimLength = characterAfterAwait === " " ? 1 : 0;

                            const range = [startOfAwait, endOfAwait + trimLength];

                            return fixer.removeRange(range);
                        }
                    }
                ]

            });
        }

        /**
         * Determines whether a thrown error from this node will be caught/handled within this function rather than immediately halting
         * this function. For example, a statement in a `try` block will always have an error handler. A statement in
         * a `catch` block will only have an error handler if there is also a `finally` block.
         * @param {ASTNode} node A node representing a location where an could be thrown
         * @returns {boolean} `true` if a thrown error will be caught/handled in this function
         */
        function hasErrorHandler(node) {
            let ancestor = node;

            while (!astUtils.isFunction(ancestor) && ancestor.type !== "Program") {
                if (ancestor.parent.type === "TryStatement" && (ancestor === ancestor.parent.block || ancestor === ancestor.parent.handler && ancestor.parent.finalizer)) {
                    return true;
                }
                ancestor = ancestor.parent;
            }
            return false;
        }

        /**
         * Checks if a node is placed in tail call position. Once `return` arguments (or arrow function expressions) can be a complex expression,
         * an `await` expression could or could not be unnecessary by the definition of this rule. So we're looking for `await` expressions that are in tail position.
         * @param {ASTNode} node A node representing the `await` expression to check
         * @returns {boolean} The checking result
         */
        function isInTailCallPosition(node) {
            if (node.parent.type === "ArrowFunctionExpression") {
                return true;
            }
            if (node.parent.type === "ReturnStatement") {
                return !hasErrorHandler(node.parent);
            }
            if (node.parent.type === "ConditionalExpression" && (node === node.parent.consequent || node === node.parent.alternate)) {
                return isInTailCallPosition(node.parent);
            }
            if (node.parent.type === "LogicalExpression" && node === node.parent.right) {
                return isInTailCallPosition(node.parent);
            }
            if (node.parent.type === "SequenceExpression" && node === node.parent.expressions[node.parent.expressions.length - 1]) {
                return isInTailCallPosition(node.parent);
            }
            return false;
        }

        return {
            AwaitExpression(node) {
                if (isInTailCallPosition(node) && !hasErrorHandler(node)) {
                    reportUnnecessaryAwait(node);
                }
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to flag when using javascript: urls
 * @author Ilya Volodin
 */
/* eslint no-script-url: 0 -- Code is checking to report such URLs */

"use strict";

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

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

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

        docs: {
            description: "Disallow `javascript:` urls",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-script-url"
        },

        schema: [],

        messages: {
            unexpectedScriptURL: "Script URL is a form of eval."
        }
    },

    create(context) {

        /**
         * Check whether a node's static value starts with "javascript:" or not.
         * And report an error for unexpected script URL.
         * @param {ASTNode} node node to check
         * @returns {void}
         */
        function check(node) {
            const value = astUtils.getStaticStringValue(node);

            if (typeof value === "string" && value.toLowerCase().indexOf("javascript:") === 0) {
                context.report({ node, messageId: "unexpectedScriptURL" });
            }
        }
        return {
            Literal(node) {
                if (node.value && typeof node.value === "string") {
                    check(node);
                }
            },
            TemplateLiteral(node) {
                if (!(node.parent && node.parent.type === "TaggedTemplateExpression")) {
                    check(node);
                }
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to disallow assignments where both sides are exactly the same
 * @author Toru Nagashima
 */

"use strict";

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

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

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

const SPACES = /\s+/gu;

/**
 * Traverses 2 Pattern nodes in parallel, then reports self-assignments.
 * @param {ASTNode|null} left A left node to traverse. This is a Pattern or
 *      a Property.
 * @param {ASTNode|null} right A right node to traverse. This is a Pattern or
 *      a Property.
 * @param {boolean} props The flag to check member expressions as well.
 * @param {Function} report A callback function to report.
 * @returns {void}
 */
function eachSelfAssignment(left, right, props, report) {
    if (!left || !right) {

        // do nothing
    } else if (
        left.type === "Identifier" &&
        right.type === "Identifier" &&
        left.name === right.name
    ) {
        report(right);
    } else if (
        left.type === "ArrayPattern" &&
        right.type === "ArrayExpression"
    ) {
        const end = Math.min(left.elements.length, right.elements.length);

        for (let i = 0; i < end; ++i) {
            const leftElement = left.elements[i];
            const rightElement = right.elements[i];

            // Avoid cases such as [...a] = [...a, 1]
            if (
                leftElement &&
                leftElement.type === "RestElement" &&
                i < right.elements.length - 1
            ) {
                break;
            }

            eachSelfAssignment(leftElement, rightElement, props, report);

            // After a spread element, those indices are unknown.
            if (rightElement && rightElement.type === "SpreadElement") {
                break;
            }
        }
    } else if (
        left.type === "RestElement" &&
        right.type === "SpreadElement"
    ) {
        eachSelfAssignment(left.argument, right.argument, props, report);
    } else if (
        left.type === "ObjectPattern" &&
        right.type === "ObjectExpression" &&
        right.properties.length >= 1
    ) {

        /*
         * Gets the index of the last spread property.
         * It's possible to overwrite properties followed by it.
         */
        let startJ = 0;

        for (let i = right.properties.length - 1; i >= 0; --i) {
            const propType = right.properties[i].type;

            if (propType === "SpreadElement" || propType === "ExperimentalSpreadProperty") {
                startJ = i + 1;
                break;
            }
        }

        for (let i = 0; i < left.properties.length; ++i) {
            for (let j = startJ; j < right.properties.length; ++j) {
                eachSelfAssignment(
                    left.properties[i],
                    right.properties[j],
                    props,
                    report
                );
            }
        }
    } else if (
        left.type === "Property" &&
        right.type === "Property" &&
        right.kind === "init" &&
        !right.method
    ) {
        const leftName = astUtils.getStaticPropertyName(left);

        if (leftName !== null && leftName === astUtils.getStaticPropertyName(right)) {
            eachSelfAssignment(left.value, right.value, props, report);
        }
    } else if (
        props &&
        astUtils.skipChainExpression(left).type === "MemberExpression" &&
        astUtils.skipChainExpression(right).type === "MemberExpression" &&
        astUtils.isSameReference(left, right)
    ) {
        report(right);
    }
}

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

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

        docs: {
            description: "Disallow assignments where both sides are exactly the same",
            recommended: true,
            url: "https://eslint.org/docs/latest/rules/no-self-assign"
        },

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

        messages: {
            selfAssignment: "'{{name}}' is assigned to itself."
        }
    },

    create(context) {
        const sourceCode = context.sourceCode;
        const [{ props = true } = {}] = context.options;

        /**
         * Reports a given node as self assignments.
         * @param {ASTNode} node A node to report. This is an Identifier node.
         * @returns {void}
         */
        function report(node) {
            context.report({
                node,
                messageId: "selfAssignment",
                data: {
                    name: sourceCode.getText(node).replace(SPACES, "")
                }
            });
        }

        return {
            AssignmentExpression(node) {
                if (["=", "&&=", "||=", "??="].includes(node.operator)) {
                    eachSelfAssignment(node.left, node.right, props, report);
                }
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to flag comparison where left part is the same as the right
 * part.
 * @author Ilya Volodin
 */

"use strict";

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

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

        docs: {
            description: "Disallow comparisons where both sides are exactly the same",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-self-compare"
        },

        schema: [],

        messages: {
            comparingToSelf: "Comparing to itself is potentially pointless."
        }
    },

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

        /**
         * Determines whether two nodes are composed of the same tokens.
         * @param {ASTNode} nodeA The first node
         * @param {ASTNode} nodeB The second node
         * @returns {boolean} true if the nodes have identical token representations
         */
        function hasSameTokens(nodeA, nodeB) {
            const tokensA = sourceCode.getTokens(nodeA);
            const tokensB = sourceCode.getTokens(nodeB);

            return tokensA.length === tokensB.length &&
                tokensA.every((token, index) => token.type === tokensB[index].type && token.value === tokensB[index].value);
        }

        return {

            BinaryExpression(node) {
                const operators = new Set(["===", "==", "!==", "!=", ">", "<", ">=", "<="]);

                if (operators.has(node.operator) && hasSameTokens(node.left, node.right)) {
                    context.report({ node, messageId: "comparingToSelf" });
                }
            }
        };

    }
};


code:
/**
 * @fileoverview Rule to flag use of comma operator
 * @author Brandon Mills
 */

"use strict";

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

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

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

const DEFAULT_OPTIONS = {
    allowInParentheses: true
};

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

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

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

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

        messages: {
            unexpectedCommaExpression: "Unexpected use of comma operator."
        }
    },

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

        /**
         * Parts of the grammar that are required to have parens.
         */
        const parenthesized = {
            DoWhileStatement: "test",
            IfStatement: "test",
            SwitchStatement: "discriminant",
            WhileStatement: "test",
            WithStatement: "object",
            ArrowFunctionExpression: "body"

            /*
             * Omitting CallExpression - commas are parsed as argument separators
             * Omitting NewExpression - commas are parsed as argument separators
             * Omitting ForInStatement - parts aren't individually parenthesised
             * Omitting ForStatement - parts aren't individually parenthesised
             */
        };

        /**
         * Determines whether a node is required by the grammar to be wrapped in
         * parens, e.g. the test of an if statement.
         * @param {ASTNode} node The AST node
         * @returns {boolean} True if parens around node belong to parent node.
         */
        function requiresExtraParens(node) {
            return node.parent && parenthesized[node.parent.type] &&
                    node === node.parent[parenthesized[node.parent.type]];
        }

        /**
         * Check if a node is wrapped in parens.
         * @param {ASTNode} node The AST node
         * @returns {boolean} True if the node has a paren on each side.
         */
        function isParenthesised(node) {
            return astUtils.isParenthesised(sourceCode, node);
        }

        /**
         * Check if a node is wrapped in two levels of parens.
         * @param {ASTNode} node The AST node
         * @returns {boolean} True if two parens surround the node on each side.
         */
        function isParenthesisedTwice(node) {
            const previousToken = sourceCode.getTokenBefore(node, 1),
                nextToken = sourceCode.getTokenAfter(node, 1);

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

        return {
            SequenceExpression(node) {

                // Always allow sequences in for statement update
                if (node.parent.type === "ForStatement" &&
                        (node === node.parent.init || node === node.parent.update)) {
                    return;
                }

                // Wrapping a sequence in extra parens indicates intent
                if (options.allowInParentheses) {
                    if (requiresExtraParens(node)) {
                        if (isParenthesisedTwice(node)) {
                            return;
                        }
                    } else {
                        if (isParenthesised(node)) {
                            return;
                        }
                    }
                }

                const firstCommaToken = sourceCode.getTokenAfter(node.expressions[0], astUtils.isCommaToken);

                context.report({ node, loc: firstCommaToken.loc, messageId: "unexpectedCommaExpression" });
            }
        };

    }
};


code:
/**
 * @fileoverview Rule to disallow returning values from setters
 * @author Milos Djermanovic
 */

"use strict";

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

const astUtils = require("./utils/ast-utils");
const { findVariable } = require("@eslint-community/eslint-utils");

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

/**
 * Determines whether the given identifier node is a reference to a global variable.
 * @param {ASTNode} node `Identifier` node to check.
 * @param {Scope} scope Scope to which the node belongs.
 * @returns {boolean} True if the identifier is a reference to a global variable.
 */
function isGlobalReference(node, scope) {
    const variable = findVariable(scope, node);

    return variable !== null && variable.scope.type === "global" && variable.defs.length === 0;
}

/**
 * Determines whether the given node is an argument of the specified global method call, at the given `index` position.
 * E.g., for given `index === 1`, this function checks for `objectName.methodName(foo, node)`, where objectName is a global variable.
 * @param {ASTNode} node The node to check.
 * @param {Scope} scope Scope to which the node belongs.
 * @param {string} objectName Name of the global object.
 * @param {string} methodName Name of the method.
 * @param {number} index The given position.
 * @returns {boolean} `true` if the node is argument at the given position.
 */
function isArgumentOfGlobalMethodCall(node, scope, objectName, methodName, index) {
    const callNode = node.parent;

    return callNode.type === "CallExpression" &&
        callNode.arguments[index] === node &&
        astUtils.isSpecificMemberAccess(callNode.callee, objectName, methodName) &&
        isGlobalReference(astUtils.skipChainExpression(callNode.callee).object, scope);
}

/**
 * Determines whether the given node is used as a property descriptor.
 * @param {ASTNode} node The node to check.
 * @param {Scope} scope Scope to which the node belongs.
 * @returns {boolean} `true` if the node is a property descriptor.
 */
function isPropertyDescriptor(node, scope) {
    if (
        isArgumentOfGlobalMethodCall(node, scope, "Object", "defineProperty", 2) ||
        isArgumentOfGlobalMethodCall(node, scope, "Reflect", "defineProperty", 2)
    ) {
        return true;
    }

    const parent = node.parent;

    if (
        parent.type === "Property" &&
        parent.value === node
    ) {
        const grandparent = parent.parent;

        if (
            grandparent.type === "ObjectExpression" &&
            (
                isArgumentOfGlobalMethodCall(grandparent, scope, "Object", "create", 1) ||
                isArgumentOfGlobalMethodCall(grandparent, scope, "Object", "defineProperties", 1)
            )
        ) {
            return true;
        }
    }

    return false;
}

/**
 * Determines whether the given function node is used as a setter function.
 * @param {ASTNode} node The node to check.
 * @param {Scope} scope Scope to which the node belongs.
 * @returns {boolean} `true` if the node is a setter.
 */
function isSetter(node, scope) {
    const parent = node.parent;

    if (
        (parent.type === "Property" || parent.type === "MethodDefinition") &&
        parent.kind === "set" &&
        parent.value === node
    ) {

        // Setter in an object literal or in a class
        return true;
    }

    if (
        parent.type === "Property" &&
        parent.value === node &&
        astUtils.getStaticPropertyName(parent) === "set" &&
        parent.parent.type === "ObjectExpression" &&
        isPropertyDescriptor(parent.parent, scope)
    ) {

        // Setter in a property descriptor
        return true;
    }

    return false;
}

/**
 * Finds function's outer scope.
 * @param {Scope} scope Function's own scope.
 * @returns {Scope} Function's outer scope.
 */
function getOuterScope(scope) {
    const upper = scope.upper;

    if (upper.type === "function-expression-name") {
        return upper.upper;
    }

    return upper;
}

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

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

        docs: {
            description: "Disallow returning values from setters",
            recommended: true,
            url: "https://eslint.org/docs/latest/rules/no-setter-return"
        },

        schema: [],

        messages: {
            returnsValue: "Setter cannot return a value."
        }
    },

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

        /**
         * Creates and pushes to the stack a function info object for the given function node.
         * @param {ASTNode} node The function node.
         * @returns {void}
         */
        function enterFunction(node) {
            const outerScope = getOuterScope(sourceCode.getScope(node));

            funcInfo = {
                upper: funcInfo,
                isSetter: isSetter(node, outerScope)
            };
        }

        /**
         * Pops the current function info object from the stack.
         * @returns {void}
         */
        function exitFunction() {
            funcInfo = funcInfo.upper;
        }

        /**
         * Reports the given node.
         * @param {ASTNode} node Node to report.
         * @returns {void}
         */
        function report(node) {
            context.report({ node, messageId: "returnsValue" });
        }

        return {

            /*
             * Function declarations cannot be setters, but we still have to track them in the `funcInfo` stack to avoid
             * false positives, because a ReturnStatement node can belong to a function declaration inside a setter.
             *
             * Note: A previously declared function can be referenced and actually used as a setter in a property descriptor,
             * but that's out of scope for this rule.
             */
            FunctionDeclaration: enterFunction,
            FunctionExpression: enterFunction,
            ArrowFunctionExpression(node) {
                enterFunction(node);

                if (funcInfo.isSetter && node.expression) {

                    // { set: foo => bar } property descriptor. Report implicit return 'bar' as the equivalent for a return statement.
                    report(node.body);
                }
            },

            "FunctionDeclaration:exit": exitFunction,
            "FunctionExpression:exit": exitFunction,
            "ArrowFunctionExpression:exit": exitFunction,

            ReturnStatement(node) {

                // Global returns (e.g., at the top level of a Node module) don't have `funcInfo`.
                if (funcInfo && funcInfo.isSetter && node.argument) {
                    report(node);
                }
            }
        };
    }
};


code:
/**
 * @fileoverview Disallow shadowing of NaN, undefined, and Infinity (ES5 section 15.1.1)
 * @author Michael Ficarra
 */
"use strict";

/**
 * Determines if a variable safely shadows undefined.
 * This is the case when a variable named `undefined` is never assigned to a value (i.e. it always shares the same value
 * as the global).
 * @param {eslintScope.Variable} variable The variable to check
 * @returns {boolean} true if this variable safely shadows `undefined`
 */
function safelyShadowsUndefined(variable) {
    return variable.name === "undefined" &&
        variable.references.every(ref => !ref.isWrite()) &&
        variable.defs.every(def => def.node.type === "VariableDeclarator" && def.node.init === null);
}

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

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

        docs: {
            description: "Disallow identifiers from shadowing restricted names",
            recommended: true,
            url: "https://eslint.org/docs/latest/rules/no-shadow-restricted-names"
        },

        schema: [],

        messages: {
            shadowingRestrictedName: "Shadowing of global property '{{name}}'."
        }
    },

    create(context) {

        const RESTRICTED = new Set(["undefined", "NaN", "Infinity", "arguments", "eval"]);
        const sourceCode = context.sourceCode;

        return {
            "VariableDeclaration, :function, CatchClause"(node) {
                for (const variable of sourceCode.getDeclaredVariables(node)) {
                    if (variable.defs.length > 0 && RESTRICTED.has(variable.name) && !safelyShadowsUndefined(variable)) {
                        context.report({
                            node: variable.defs[0].name,
                            messageId: "shadowingRestrictedName",
                            data: {
                                name: variable.name
                            }
                        });
                    }
                }
            }
        };

    }
};


code:
/**
 * @fileoverview Rule to flag on declaring variables already declared in the outer scope
 * @author Ilya Volodin
 */

"use strict";

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

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

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

const FUNC_EXPR_NODE_TYPES = new Set(["ArrowFunctionExpression", "FunctionExpression"]);
const CALL_EXPR_NODE_TYPE = new Set(["CallExpression"]);
const FOR_IN_OF_TYPE = /^For(?:In|Of)Statement$/u;
const SENTINEL_TYPE = /^(?:(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|CatchClause|ImportDeclaration|ExportNamedDeclaration)$/u;

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

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

        docs: {
            description: "Disallow variable declarations from shadowing variables declared in the outer scope",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-shadow"
        },

        schema: [
            {
                type: "object",
                properties: {
                    builtinGlobals: { type: "boolean", default: false },
                    hoist: { enum: ["all", "functions", "never"], default: "functions" },
                    allow: {
                        type: "array",
                        items: {
                            type: "string"
                        }
                    },
                    ignoreOnInitialization: { type: "boolean", default: false }
                },
                additionalProperties: false
            }
        ],

        messages: {
            noShadow: "'{{name}}' is already declared in the upper scope on line {{shadowedLine}} column {{shadowedColumn}}.",
            noShadowGlobal: "'{{name}}' is already a global variable."
        }
    },

    create(context) {

        const options = {
            builtinGlobals: context.options[0] && context.options[0].builtinGlobals,
            hoist: (context.options[0] && context.options[0].hoist) || "functions",
            allow: (context.options[0] && context.options[0].allow) || [],
            ignoreOnInitialization: context.options[0] && context.options[0].ignoreOnInitialization
        };
        const sourceCode = context.sourceCode;

        /**
         * Checks whether or not a given location is inside of the range of a given node.
         * @param {ASTNode} node An node to check.
         * @param {number} location A location to check.
         * @returns {boolean} `true` if the location is inside of the range of the node.
         */
        function isInRange(node, location) {
            return node && node.range[0] <= location && location <= node.range[1];
        }

        /**
         * Searches from the current node through its ancestry to find a matching node.
         * @param {ASTNode} node a node to get.
         * @param {(node: ASTNode) => boolean} match a callback that checks whether or not the node verifies its condition or not.
         * @returns {ASTNode|null} the matching node.
         */
        function findSelfOrAncestor(node, match) {
            let currentNode = node;

            while (currentNode && !match(currentNode)) {
                currentNode = currentNode.parent;
            }
            return currentNode;
        }

        /**
         * Finds function's outer scope.
         * @param {Scope} scope Function's own scope.
         * @returns {Scope} Function's outer scope.
         */
        function getOuterScope(scope) {
            const upper = scope.upper;

            if (upper.type === "function-expression-name") {
                return upper.upper;
            }
            return upper;
        }

        /**
         * Checks if a variable and a shadowedVariable have the same init pattern ancestor.
         * @param {Object} variable a variable to check.
         * @param {Object} shadowedVariable a shadowedVariable to check.
         * @returns {boolean} Whether or not the variable and the shadowedVariable have the same init pattern ancestor.
         */
        function isInitPatternNode(variable, shadowedVariable) {
            const outerDef = shadowedVariable.defs[0];

            if (!outerDef) {
                return false;
            }

            const { variableScope } = variable.scope;

            if (!(FUNC_EXPR_NODE_TYPES.has(variableScope.block.type) && getOuterScope(variableScope) === shadowedVariable.scope)) {
                return false;
            }

            const fun = variableScope.block;
            const { parent } = fun;

            const callExpression = findSelfOrAncestor(
                parent,
                node => CALL_EXPR_NODE_TYPE.has(node.type)
            );

            if (!callExpression) {
                return false;
            }

            let node = outerDef.name;
            const location = callExpression.range[1];

            while (node) {
                if (node.type === "VariableDeclarator") {
                    if (isInRange(node.init, location)) {
                        return true;
                    }
                    if (FOR_IN_OF_TYPE.test(node.parent.parent.type) &&
                        isInRange(node.parent.parent.right, location)
                    ) {
                        return true;
                    }
                    break;
                } else if (node.type === "AssignmentPattern") {
                    if (isInRange(node.right, location)) {
                        return true;
                    }
                } else if (SENTINEL_TYPE.test(node.type)) {
                    break;
                }

                node = node.parent;
            }

            return false;
        }

        /**
         * Check if variable name is allowed.
         * @param {ASTNode} variable The variable to check.
         * @returns {boolean} Whether or not the variable name is allowed.
         */
        function isAllowed(variable) {
            return options.allow.includes(variable.name);
        }

        /**
         * Checks if a variable of the class name in the class scope of ClassDeclaration.
         *
         * ClassDeclaration creates two variables of its name into its outer scope and its class scope.
         * So we should ignore the variable in the class scope.
         * @param {Object} variable The variable to check.
         * @returns {boolean} Whether or not the variable of the class name in the class scope of ClassDeclaration.
         */
        function isDuplicatedClassNameVariable(variable) {
            const block = variable.scope.block;

            return block.type === "ClassDeclaration" && block.id === variable.identifiers[0];
        }

        /**
         * Checks if a variable is inside the initializer of scopeVar.
         *
         * To avoid reporting at declarations such as `var a = function a() {};`.
         * But it should report `var a = function(a) {};` or `var a = function() { function a() {} };`.
         * @param {Object} variable The variable to check.
         * @param {Object} scopeVar The scope variable to look for.
         * @returns {boolean} Whether or not the variable is inside initializer of scopeVar.
         */
        function isOnInitializer(variable, scopeVar) {
            const outerScope = scopeVar.scope;
            const outerDef = scopeVar.defs[0];
            const outer = outerDef && outerDef.parent && outerDef.parent.range;
            const innerScope = variable.scope;
            const innerDef = variable.defs[0];
            const inner = innerDef && innerDef.name.range;

            return (
                outer &&
                 inner &&
                 outer[0] < inner[0] &&
                 inner[1] < outer[1] &&
                 ((innerDef.type === "FunctionName" && innerDef.node.type === "FunctionExpression") || innerDef.node.type === "ClassExpression") &&
                 outerScope === innerScope.upper
            );
        }

        /**
         * Get a range of a variable's identifier node.
         * @param {Object} variable The variable to get.
         * @returns {Array|undefined} The range of the variable's identifier node.
         */
        function getNameRange(variable) {
            const def = variable.defs[0];

            return def && def.name.range;
        }

        /**
         * Get declared line and column of a variable.
         * @param {eslint-scope.Variable} variable The variable to get.
         * @returns {Object} The declared line and column of the variable.
         */
        function getDeclaredLocation(variable) {
            const identifier = variable.identifiers[0];
            let obj;

            if (identifier) {
                obj = {
                    global: false,
                    line: identifier.loc.start.line,
                    column: identifier.loc.start.column + 1
                };
            } else {
                obj = {
                    global: true
                };
            }
            return obj;
        }

        /**
         * Checks if a variable is in TDZ of scopeVar.
         * @param {Object} variable The variable to check.
         * @param {Object} scopeVar The variable of TDZ.
         * @returns {boolean} Whether or not the variable is in TDZ of scopeVar.
         */
        function isInTdz(variable, scopeVar) {
            const outerDef = scopeVar.defs[0];
            const inner = getNameRange(variable);
            const outer = getNameRange(scopeVar);

            return (
                inner &&
                 outer &&
                 inner[1] < outer[0] &&

                 // Excepts FunctionDeclaration if is {"hoist":"function"}.
                 (options.hoist !== "functions" || !outerDef || outerDef.node.type !== "FunctionDeclaration")
            );
        }

        /**
         * Checks the current context for shadowed variables.
         * @param {Scope} scope Fixme
         * @returns {void}
         */
        function checkForShadows(scope) {
            const variables = scope.variables;

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

                // Skips "arguments" or variables of a class name in the class scope of ClassDeclaration.
                if (variable.identifiers.length === 0 ||
                     isDuplicatedClassNameVariable(variable) ||
                     isAllowed(variable)
                ) {
                    continue;
                }

                // Gets shadowed variable.
                const shadowed = astUtils.getVariableByName(scope.upper, variable.name);

                if (shadowed &&
                      (shadowed.identifiers.length > 0 || (options.builtinGlobals && "writeable" in shadowed)) &&
                      !isOnInitializer(variable, shadowed) &&
                      !(options.ignoreOnInitialization && isInitPatternNode(variable, shadowed)) &&
                      !(options.hoist !== "all" && isInTdz(variable, shadowed))
                ) {
                    const location = getDeclaredLocation(shadowed);
                    const messageId = location.global ? "noShadowGlobal" : "noShadow";
                    const data = { name: variable.name };

                    if (!location.global) {
                        data.shadowedLine = location.line;
                        data.shadowedColumn = location.column;
                    }
                    context.report({
                        node: variable.identifiers[0],
                        messageId,
                        data
                    });
                }
            }
        }

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

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

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

    }
};


code:
/**
 * @fileoverview Rule to check that spaced function application
 * @author Matt DuVall <http://www.mattduvall.com>
 * @deprecated in ESLint v3.3.0
 */

"use strict";

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

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

        docs: {
            description: "Disallow spacing between function identifiers and their applications (deprecated)",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-spaced-func"
        },

        deprecated: true,

        replacedBy: ["func-call-spacing"],

        fixable: "whitespace",
        schema: [],

        messages: {
            noSpacedFunction: "Unexpected space between function name and paren."
        }
    },

    create(context) {

        const sourceCode = context.sourceCode;

        /**
         * Check if open space is present in a function name
         * @param {ASTNode} node node to evaluate
         * @returns {void}
         * @private
         */
        function detectOpenSpaces(node) {
            const lastCalleeToken = sourceCode.getLastToken(node.callee);
            let prevToken = lastCalleeToken,
                parenToken = sourceCode.getTokenAfter(lastCalleeToken);

            // advances to an open parenthesis.
            while (
                parenToken &&
                parenToken.range[1] < node.range[1] &&
                parenToken.value !== "("
            ) {
                prevToken = parenToken;
                parenToken = sourceCode.getTokenAfter(parenToken);
            }

            // look for a space between the callee and the open paren
            if (parenToken &&
                parenToken.range[1] < node.range[1] &&
                sourceCode.isSpaceBetweenTokens(prevToken, parenToken)
            ) {
                context.report({
                    node,
                    loc: lastCalleeToken.loc.start,
                    messageId: "noSpacedFunction",
                    fix(fixer) {
                        return fixer.removeRange([prevToken.range[1], parenToken.range[0]]);
                    }
                });
            }
        }

        return {
            CallExpression: detectOpenSpaces,
            NewExpression: detectOpenSpaces
        };

    }
};


code:
/**
 * @fileoverview Disallow sparse arrays
 * @author Nicholas C. Zakas
 */
"use strict";

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

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

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

        schema: [],

        messages: {
            unexpectedSparseArray: "Unexpected comma in middle of array."
        }
    },

    create(context) {

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

        return {

            ArrayExpression(node) {

                const emptySpot = node.elements.includes(null);

                if (emptySpot) {
                    context.report({ node, messageId: "unexpectedSparseArray" });
                }
            }

        };

    }
};


code:
/**
 * @fileoverview Rule to check for properties whose identifier ends with the string Sync
 * @author Matt DuVall<http://mattduvall.com/>
 * @deprecated in ESLint v7.0.0
 */

"use strict";

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

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

        replacedBy: [],

        type: "suggestion",

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

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

        messages: {
            noSync: "Unexpected sync method: '{{propertyName}}'."
        }
    },

    create(context) {
        const selector = context.options[0] && context.options[0].allowAtRootLevel
            ? ":function MemberExpression[property.name=/.*Sync$/]"
            : "MemberExpression[property.name=/.*Sync$/]";

        return {
            [selector](node) {
                context.report({
                    node,
                    messageId: "noSync",
                    data: {
                        propertyName: node.property.name
                    }
                });
            }
        };

    }
};


code:
/**
 * @fileoverview Rule to check for tabs inside a file
 * @author Gyandeep Singh
 * @deprecated in ESLint v8.53.0
 */

"use strict";

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

const tabRegex = /\t+/gu;
const anyNonWhitespaceRegex = /\S/u;

//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------

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

        docs: {
            description: "Disallow all tabs",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-tabs"
        },
        schema: [{
            type: "object",
            properties: {
                allowIndentationTabs: {
                    type: "boolean",
                    default: false
                }
            },
            additionalProperties: false
        }],

        messages: {
            unexpectedTab: "Unexpected tab character."
        }
    },

    create(context) {
        const sourceCode = context.sourceCode;
        const allowIndentationTabs = context.options && context.options[0] && context.options[0].allowIndentationTabs;

        return {
            Program(node) {
                sourceCode.getLines().forEach((line, index) => {
                    let match;

                    while ((match = tabRegex.exec(line)) !== null) {
                        if (allowIndentationTabs && !anyNonWhitespaceRegex.test(line.slice(0, match.index))) {
                            continue;
                        }

                        context.report({
                            node,
                            loc: {
                                start: {
                                    line: index + 1,
                                    column: match.index
                                },
                                end: {
                                    line: index + 1,
                                    column: match.index + match[0].length
                                }
                            },
                            messageId: "unexpectedTab"
                        });
                    }
                });
            }
        };
    }
};


code:
/**
 * @fileoverview Warn when using template string syntax in regular strings
 * @author Jeroen Engels
 */
"use strict";

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

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

        docs: {
            description: "Disallow template literal placeholder syntax in regular strings",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-template-curly-in-string"
        },

        schema: [],

        messages: {
            unexpectedTemplateExpression: "Unexpected template string expression."
        }
    },

    create(context) {
        const regex = /\$\{[^}]+\}/u;

        return {
            Literal(node) {
                if (typeof node.value === "string" && regex.test(node.value)) {
                    context.report({
                        node,
                        messageId: "unexpectedTemplateExpression"
                    });
                }
            }
        };

    }
};


code:
/**
 * @fileoverview Rule to flag use of ternary operators.
 * @author Ian Christian Myers
 */

"use strict";

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

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

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

        schema: [],

        messages: {
            noTernaryOperator: "Ternary operator used."
        }
    },

    create(context) {

        return {

            ConditionalExpression(node) {
                context.report({ node, messageId: "noTernaryOperator" });
            }

        };

    }
};


code:
/**
 * @fileoverview A rule to disallow using `this`/`super` before `super()`.
 * @author Toru Nagashima
 */

"use strict";

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

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

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

/**
 * Checks whether or not a given node is a constructor.
 * @param {ASTNode} node A node to check. This node type is one of
 *   `Program`, `FunctionDeclaration`, `FunctionExpression`, and
 *   `ArrowFunctionExpression`.
 * @returns {boolean} `true` if the node is a constructor.
 */
function isConstructorFunction(node) {
    return (
        node.type === "FunctionExpression" &&
        node.parent.type === "MethodDefinition" &&
        node.parent.kind === "constructor"
    );
}

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

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

        docs: {
            description: "Disallow `this`/`super` before calling `super()` in constructors",
            recommended: true,
            url: "https://eslint.org/docs/latest/rules/no-this-before-super"
        },

        schema: [],

        messages: {
            noBeforeSuper: "'{{kind}}' is not allowed before 'super()'."
        }
    },

    create(context) {

        /*
         * Information for each constructor.
         * - upper:      Information of the upper constructor.
         * - hasExtends: A flag which shows whether the owner class has a valid
         *   `extends` part.
         * - scope:      The scope of the owner class.
         * - codePath:   The code path of this constructor.
         */
        let funcInfo = null;

        /*
         * Information for each code path segment.
         * Each key is the id of a code path segment.
         * Each value is an object:
         * - superCalled:  The flag which shows `super()` called in all code paths.
         * - invalidNodes: The array of invalid ThisExpression and Super nodes.
         */
        let segInfoMap = Object.create(null);

        /**
         * Gets whether or not `super()` is called in a given code path segment.
         * @param {CodePathSegment} segment A code path segment to get.
         * @returns {boolean} `true` if `super()` is called.
         */
        function isCalled(segment) {
            return !segment.reachable || segInfoMap[segment.id].superCalled;
        }

        /**
         * Checks whether or not this is in a constructor.
         * @returns {boolean} `true` if this is in a constructor.
         */
        function isInConstructorOfDerivedClass() {
            return Boolean(funcInfo && funcInfo.isConstructor && funcInfo.hasExtends);
        }

        /**
         * Determines if every segment in a set has been called.
         * @param {Set<CodePathSegment>} segments The segments to search.
         * @returns {boolean} True if every segment has been called; false otherwise.
         */
        function isEverySegmentCalled(segments) {
            for (const segment of segments) {
                if (!isCalled(segment)) {
                    return false;
                }
            }

            return true;
        }

        /**
         * Checks whether or not this is before `super()` is called.
         * @returns {boolean} `true` if this is before `super()` is called.
         */
        function isBeforeCallOfSuper() {
            return (
                isInConstructorOfDerivedClass() &&
                !isEverySegmentCalled(funcInfo.currentSegments)
            );
        }

        /**
         * Sets a given node as invalid.
         * @param {ASTNode} node A node to set as invalid. This is one of
         *      a ThisExpression and a Super.
         * @returns {void}
         */
        function setInvalid(node) {
            const segments = funcInfo.currentSegments;

            for (const segment of segments) {
                if (segment.reachable) {
                    segInfoMap[segment.id].invalidNodes.push(node);
                }
            }
        }

        /**
         * Sets the current segment as `super` was called.
         * @returns {void}
         */
        function setSuperCalled() {
            const segments = funcInfo.currentSegments;

            for (const segment of segments) {
                if (segment.reachable) {
                    segInfoMap[segment.id].superCalled = true;
                }
            }
        }

        return {

            /**
             * Adds information of a constructor into the stack.
             * @param {CodePath} codePath A code path which was started.
             * @param {ASTNode} node The current node.
             * @returns {void}
             */
            onCodePathStart(codePath, node) {
                if (isConstructorFunction(node)) {

                    // Class > ClassBody > MethodDefinition > FunctionExpression
                    const classNode = node.parent.parent.parent;

                    funcInfo = {
                        upper: funcInfo,
                        isConstructor: true,
                        hasExtends: Boolean(
                            classNode.superClass &&
                            !astUtils.isNullOrUndefined(classNode.superClass)
                        ),
                        codePath,
                        currentSegments: new Set()
                    };
                } else {
                    funcInfo = {
                        upper: funcInfo,
                        isConstructor: false,
                        hasExtends: false,
                        codePath,
                        currentSegments: new Set()
                    };
                }
            },

            /**
             * Removes the top of stack item.
             *
             * And this traverses all segments of this code path then reports every
             * invalid node.
             * @param {CodePath} codePath A code path which was ended.
             * @returns {void}
             */
            onCodePathEnd(codePath) {
                const isDerivedClass = funcInfo.hasExtends;

                funcInfo = funcInfo.upper;
                if (!isDerivedClass) {
                    return;
                }

                codePath.traverseSegments((segment, controller) => {
                    const info = segInfoMap[segment.id];

                    for (let i = 0; i < info.invalidNodes.length; ++i) {
                        const invalidNode = info.invalidNodes[i];

                        context.report({
                            messageId: "noBeforeSuper",
                            node: invalidNode,
                            data: {
                                kind: invalidNode.type === "Super" ? "super" : "this"
                            }
                        });
                    }

                    if (info.superCalled) {
                        controller.skip();
                    }
                });
            },

            /**
             * Initialize information of a given code path segment.
             * @param {CodePathSegment} segment A code path segment to initialize.
             * @returns {void}
             */
            onCodePathSegmentStart(segment) {
                funcInfo.currentSegments.add(segment);

                if (!isInConstructorOfDerivedClass()) {
                    return;
                }

                // Initialize info.
                segInfoMap[segment.id] = {
                    superCalled: (
                        segment.prevSegments.length > 0 &&
                        segment.prevSegments.every(isCalled)
                    ),
                    invalidNodes: []
                };
            },

            onUnreachableCodePathSegmentStart(segment) {
                funcInfo.currentSegments.add(segment);
            },

            onUnreachableCodePathSegmentEnd(segment) {
                funcInfo.currentSegments.delete(segment);
            },

            onCodePathSegmentEnd(segment) {
                funcInfo.currentSegments.delete(segment);
            },

            /**
             * Update information of the code path segment when a code path was
             * looped.
             * @param {CodePathSegment} fromSegment The code path segment of the
             *      end of a loop.
             * @param {CodePathSegment} toSegment A code path segment of the head
             *      of a loop.
             * @returns {void}
             */
            onCodePathSegmentLoop(fromSegment, toSegment) {
                if (!isInConstructorOfDerivedClass()) {
                    return;
                }

                // Update information inside of the loop.
                funcInfo.codePath.traverseSegments(
                    { first: toSegment, last: fromSegment },
                    (segment, controller) => {
                        const info = segInfoMap[segment.id];

                        if (info.superCalled) {
                            info.invalidNodes = [];
                            controller.skip();
                        } else if (
                            segment.prevSegments.length > 0 &&
                            segment.prevSegments.every(isCalled)
                        ) {
                            info.superCalled = true;
                            info.invalidNodes = [];
                        }
                    }
                );
            },

            /**
             * Reports if this is before `super()`.
             * @param {ASTNode} node A target node.
             * @returns {void}
             */
            ThisExpression(node) {
                if (isBeforeCallOfSuper()) {
                    setInvalid(node);
                }
            },

            /**
             * Reports if this is before `super()`.
             * @param {ASTNode} node A target node.
             * @returns {void}
             */
            Super(node) {
                if (!astUtils.isCallee(node) && isBeforeCallOfSuper()) {
                    setInvalid(node);
                }
            },

            /**
             * Marks `super()` called.
             * @param {ASTNode} node A target node.
             * @returns {void}
             */
            "CallExpression:exit"(node) {
                if (node.callee.type === "Super" && isBeforeCallOfSuper()) {
                    setSuperCalled();
                }
            },

            /**
             * Resets state.
             * @returns {void}
             */
            "Program:exit"() {
                segInfoMap = Object.create(null);
            }
        };
    }
};


code:
/**
 * @fileoverview Rule to restrict what can be thrown as an exception.
 * @author Dieter Oberkofler
 */

"use strict";

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

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

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

        docs: {
            description: "Disallow throwing literals as exceptions",
            recommended: false,
            url: "https://eslint.org/docs/latest/rules/no-throw-literal"
        },

        schema: [],

        messages: {
            object: "Expected an error object to be thrown.",
            undef: "Do not throw undefined."
        }
    },

    create(context) {

        return {

            ThrowStatement(node) {
                if (!astUtils.couldBeError(node.argument)) {
                    context.report({ node, messageId: "object" });
                } else if (node.argument.type === "Identifier") {
                    if (node.argument.name === "undefined") {
                        context.report({ node, messageId: "undef" });
                    }
                }

            }

        };

    }
};