2 * @fileoverview Rule to enforce grouped require statements for Node.JS
3 * @author Raphael Pigulla
4 * @deprecated in ESLint v7.0.0
9 //------------------------------------------------------------------------------
11 //------------------------------------------------------------------------------
13 /** @type {import('../shared/types').Rule} */
23 description
: "Disallow `require` calls to be mixed with regular variable declarations",
25 url
: "https://eslint.org/docs/rules/no-mixed-requires"
44 additionalProperties
: false
51 noMixRequire
: "Do not mix 'require' and other declarations.",
52 noMixCoreModuleFileComputed
: "Do not mix core, module, file and computed requires."
58 const options
= context
.options
[0];
62 if (typeof options
=== "object") {
63 grouping
= options
.grouping
;
64 allowCall
= options
.allowCall
;
70 * Returns the list of built-in modules.
71 * @returns {string[]} An array of built-in Node.js modules.
73 function getBuiltinModules() {
76 * This list is generated using:
77 * `require("repl")._builtinLibs.concat('repl').sort()`
78 * This particular list is as per nodejs v0.12.2 and iojs v0.7.1
81 "assert", "buffer", "child_process", "cluster", "crypto",
82 "dgram", "dns", "domain", "events", "fs", "http", "https",
83 "net", "os", "path", "punycode", "querystring", "readline",
84 "repl", "smalloc", "stream", "string_decoder", "tls", "tty",
85 "url", "util", "v8", "vm", "zlib"
89 const BUILTIN_MODULES
= getBuiltinModules();
91 const DECL_REQUIRE
= "require",
92 DECL_UNINITIALIZED
= "uninitialized",
95 const REQ_CORE
= "core",
97 REQ_MODULE
= "module",
98 REQ_COMPUTED
= "computed";
101 * Determines the type of a declaration statement.
102 * @param {ASTNode} initExpression The init node of the VariableDeclarator.
103 * @returns {string} The type of declaration represented by the expression.
105 function getDeclarationType(initExpression
) {
106 if (!initExpression
) {
109 return DECL_UNINITIALIZED
;
112 if (initExpression
.type
=== "CallExpression" &&
113 initExpression
.callee
.type
=== "Identifier" &&
114 initExpression
.callee
.name
=== "require"
117 // "var x = require('util');"
121 initExpression
.type
=== "CallExpression" &&
122 initExpression
.callee
.type
=== "CallExpression"
125 // "var x = require('diagnose')('sub-module');"
126 return getDeclarationType(initExpression
.callee
);
128 if (initExpression
.type
=== "MemberExpression") {
130 // "var x = require('glob').Glob;"
131 return getDeclarationType(initExpression
.object
);
139 * Determines the type of module that is loaded via require.
140 * @param {ASTNode} initExpression The init node of the VariableDeclarator.
141 * @returns {string} The module type.
143 function inferModuleType(initExpression
) {
144 if (initExpression
.type
=== "MemberExpression") {
146 // "var x = require('glob').Glob;"
147 return inferModuleType(initExpression
.object
);
149 if (initExpression
.arguments
.length
=== 0) {
151 // "var x = require();"
155 const arg
= initExpression
.arguments
[0];
157 if (arg
.type
!== "Literal" || typeof arg
.value
!== "string") {
159 // "var x = require(42);"
163 if (BUILTIN_MODULES
.includes(arg
.value
)) {
165 // "var fs = require('fs');"
168 if (/^\.{0,2}\//u.test(arg
.value
)) {
170 // "var utils = require('./utils');"
174 // "var async = require('async');"
180 * Check if the list of variable declarations is mixed, i.e. whether it
181 * contains both require and other declarations.
182 * @param {ASTNode} declarations The list of VariableDeclarators.
183 * @returns {boolean} True if the declarations are mixed, false if not.
185 function isMixed(declarations
) {
188 declarations
.forEach(declaration
=> {
189 const type
= getDeclarationType(declaration
.init
);
191 contains
[type
] = true;
195 contains
[DECL_REQUIRE
] &&
196 (contains
[DECL_UNINITIALIZED
] || contains
[DECL_OTHER
])
201 * Check if all require declarations in the given list are of the same
203 * @param {ASTNode} declarations The list of VariableDeclarators.
204 * @returns {boolean} True if the declarations are grouped, false if not.
206 function isGrouped(declarations
) {
209 declarations
.forEach(declaration
=> {
210 if (getDeclarationType(declaration
.init
) === DECL_REQUIRE
) {
211 found
[inferModuleType(declaration
.init
)] = true;
215 return Object
.keys(found
).length
<= 1;
221 VariableDeclaration(node
) {
223 if (isMixed(node
.declarations
)) {
226 messageId
: "noMixRequire"
228 } else if (grouping
&& !isGrouped(node
.declarations
)) {
231 messageId
: "noMixCoreModuleFileComputed"