| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 | /** * @author Raphael Pigulla * See LICENSE file in root directory for full license. */"use strict"// This list is generated using://     `require("module").builtinModules`//// This was last updated using Node v13.8.0.const BUILTIN_MODULES = [    "_http_agent",    "_http_client",    "_http_common",    "_http_incoming",    "_http_outgoing",    "_http_server",    "_stream_duplex",    "_stream_passthrough",    "_stream_readable",    "_stream_transform",    "_stream_wrap",    "_stream_writable",    "_tls_common",    "_tls_wrap",    "assert",    "async_hooks",    "buffer",    "child_process",    "cluster",    "console",    "constants",    "crypto",    "dgram",    "dns",    "domain",    "events",    "fs",    "http",    "http2",    "https",    "inspector",    "module",    "net",    "os",    "path",    "perf_hooks",    "process",    "punycode",    "querystring",    "readline",    "repl",    "stream",    "string_decoder",    "sys",    "timers",    "tls",    "trace_events",    "tty",    "url",    "util",    "v8",    "vm",    "worker_threads",    "zlib",]module.exports = {    meta: {        type: "suggestion",        docs: {            description:                "disallow `require` calls to be mixed with regular variable declarations",            category: "Stylistic Issues",            recommended: false,            url:                "https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-mixed-requires.md",        },        fixable: null,        schema: [            {                oneOf: [                    {                        type: "boolean",                    },                    {                        type: "object",                        properties: {                            grouping: {                                type: "boolean",                            },                            allowCall: {                                type: "boolean",                            },                        },                        additionalProperties: false,                    },                ],            },        ],        messages: {            noMixRequire: "Do not mix 'require' and other declarations.",            noMixCoreModuleFileComputed:                "Do not mix core, module, file and computed requires.",        },    },    create(context) {        const options = context.options[0]        let grouping = false        let allowCall = false        if (typeof options === "object") {            grouping = options.grouping            allowCall = options.allowCall        } else {            grouping = Boolean(options)        }        const DECL_REQUIRE = "require"        const DECL_UNINITIALIZED = "uninitialized"        const DECL_OTHER = "other"        const REQ_CORE = "core"        const REQ_FILE = "file"        const REQ_MODULE = "module"        const REQ_COMPUTED = "computed"        /**         * Determines the type of a declaration statement.         * @param {ASTNode} initExpression The init node of the VariableDeclarator.         * @returns {string} The type of declaration represented by the expression.         */        function getDeclarationType(initExpression) {            if (!initExpression) {                // "var x;"                return DECL_UNINITIALIZED            }            if (                initExpression.type === "CallExpression" &&                initExpression.callee.type === "Identifier" &&                initExpression.callee.name === "require"            ) {                // "var x = require('util');"                return DECL_REQUIRE            }            if (                allowCall &&                initExpression.type === "CallExpression" &&                initExpression.callee.type === "CallExpression"            ) {                // "var x = require('diagnose')('sub-module');"                return getDeclarationType(initExpression.callee)            }            if (initExpression.type === "MemberExpression") {                // "var x = require('glob').Glob;"                return getDeclarationType(initExpression.object)            }            // "var x = 42;"            return DECL_OTHER        }        /**         * Determines the type of module that is loaded via require.         * @param {ASTNode} initExpression The init node of the VariableDeclarator.         * @returns {string} The module type.         */        function inferModuleType(initExpression) {            if (initExpression.type === "MemberExpression") {                // "var x = require('glob').Glob;"                return inferModuleType(initExpression.object)            }            if (initExpression.arguments.length === 0) {                // "var x = require();"                return REQ_COMPUTED            }            const arg = initExpression.arguments[0]            if (arg.type !== "Literal" || typeof arg.value !== "string") {                // "var x = require(42);"                return REQ_COMPUTED            }            if (BUILTIN_MODULES.indexOf(arg.value) !== -1) {                // "var fs = require('fs');"                return REQ_CORE            }            if (/^\.{0,2}\//u.test(arg.value)) {                // "var utils = require('./utils');"                return REQ_FILE            }            // "var async = require('async');"            return REQ_MODULE        }        /**         * Check if the list of variable declarations is mixed, i.e. whether it         * contains both require and other declarations.         * @param {ASTNode} declarations The list of VariableDeclarators.         * @returns {boolean} True if the declarations are mixed, false if not.         */        function isMixed(declarations) {            const contains = {}            for (const declaration of declarations) {                const type = getDeclarationType(declaration.init)                contains[type] = true            }            return Boolean(                contains[DECL_REQUIRE] &&                    (contains[DECL_UNINITIALIZED] || contains[DECL_OTHER])            )        }        /**         * Check if all require declarations in the given list are of the same         * type.         * @param {ASTNode} declarations The list of VariableDeclarators.         * @returns {boolean} True if the declarations are grouped, false if not.         */        function isGrouped(declarations) {            const found = {}            for (const declaration of declarations) {                if (getDeclarationType(declaration.init) === DECL_REQUIRE) {                    found[inferModuleType(declaration.init)] = true                }            }            return Object.keys(found).length <= 1        }        return {            VariableDeclaration(node) {                if (isMixed(node.declarations)) {                    context.report({                        node,                        messageId: "noMixRequire",                    })                } else if (grouping && !isGrouped(node.declarations)) {                    context.report({                        node,                        messageId: "noMixCoreModuleFileComputed",                    })                }            },        }    },}
 |