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",
- })
- }
- },
- }
- },
- }
|