| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 | /** * @fileoverview Restrict usage of specified globals. * @author Benoît Zugmeyer */"use strict";//------------------------------------------------------------------------------// Helpers//------------------------------------------------------------------------------const DEFAULT_MESSAGE_TEMPLATE = "Unexpected use of '{{name}}'.",    CUSTOM_MESSAGE_TEMPLATE = "Unexpected use of '{{name}}'. {{customMessage}}";//------------------------------------------------------------------------------// Rule Definition//------------------------------------------------------------------------------module.exports = {    meta: {        docs: {            description: "disallow specified global variables",            category: "Variables",            recommended: false,            url: "https://eslint.org/docs/rules/no-restricted-globals"        },        schema: {            type: "array",            items: {                oneOf: [                    {                        type: "string"                    },                    {                        type: "object",                        properties: {                            name: { type: "string" },                            message: { type: "string" }                        },                        required: ["name"],                        additionalProperties: false                    }                ]            },            uniqueItems: true,            minItems: 0        }    },    create(context) {        // If no globals are restricted, we don't need to do anything        if (context.options.length === 0) {            return {};        }        const restrictedGlobalMessages = context.options.reduce((memo, option) => {            if (typeof option === "string") {                memo[option] = null;            } else {                memo[option.name] = option.message;            }            return memo;        }, {});        /**         * Report a variable to be used as a restricted global.         * @param {Reference} reference the variable reference         * @returns {void}         * @private         */        function reportReference(reference) {            const name = reference.identifier.name,                customMessage = restrictedGlobalMessages[name],                message = customMessage                    ? CUSTOM_MESSAGE_TEMPLATE                    : DEFAULT_MESSAGE_TEMPLATE;            context.report({                node: reference.identifier,                message,                data: {                    name,                    customMessage                }            });        }        /**         * Check if the given name is a restricted global name.         * @param {string} name name of a variable         * @returns {boolean} whether the variable is a restricted global or not         * @private         */        function isRestricted(name) {            return restrictedGlobalMessages.hasOwnProperty(name);        }        return {            Program() {                const scope = context.getScope();                // Report variables declared elsewhere (ex: variables defined as "global" by eslint)                scope.variables.forEach(variable => {                    if (!variable.defs.length && isRestricted(variable.name)) {                        variable.references.forEach(reportReference);                    }                });                // Report variables not declared at all                scope.through.forEach(reference => {                    if (isRestricted(reference.identifier.name)) {                        reportReference(reference);                    }                });            }        };    }};
 |