summaryrefslogtreecommitdiff
path: root/tools/node_modules/eslint/lib/rules/no-mixed-requires.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/node_modules/eslint/lib/rules/no-mixed-requires.js')
-rw-r--r--tools/node_modules/eslint/lib/rules/no-mixed-requires.js220
1 files changed, 220 insertions, 0 deletions
diff --git a/tools/node_modules/eslint/lib/rules/no-mixed-requires.js b/tools/node_modules/eslint/lib/rules/no-mixed-requires.js
new file mode 100644
index 0000000000..171052a52a
--- /dev/null
+++ b/tools/node_modules/eslint/lib/rules/no-mixed-requires.js
@@ -0,0 +1,220 @@
+/**
+ * @fileoverview Rule to enforce grouped require statements for Node.JS
+ * @author Raphael Pigulla
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "disallow `require` calls to be mixed with regular variable declarations",
+ category: "Node.js and CommonJS",
+ recommended: false
+ },
+
+ schema: [
+ {
+ oneOf: [
+ {
+ type: "boolean"
+ },
+ {
+ type: "object",
+ properties: {
+ grouping: {
+ type: "boolean"
+ },
+ allowCall: {
+ type: "boolean"
+ }
+ },
+ additionalProperties: false
+ }
+ ]
+ }
+ ]
+ },
+
+ create(context) {
+
+ const options = context.options[0];
+ let grouping = false,
+ allowCall = false;
+
+ if (typeof options === "object") {
+ grouping = options.grouping;
+ allowCall = options.allowCall;
+ } else {
+ grouping = !!options;
+ }
+
+ /**
+ * Returns the list of built-in modules.
+ *
+ * @returns {string[]} An array of built-in Node.js modules.
+ */
+ function getBuiltinModules() {
+
+ /*
+ * This list is generated using:
+ * `require("repl")._builtinLibs.concat('repl').sort()`
+ * This particular list is as per nodejs v0.12.2 and iojs v0.7.1
+ */
+ return [
+ "assert", "buffer", "child_process", "cluster", "crypto",
+ "dgram", "dns", "domain", "events", "fs", "http", "https",
+ "net", "os", "path", "punycode", "querystring", "readline",
+ "repl", "smalloc", "stream", "string_decoder", "tls", "tty",
+ "url", "util", "v8", "vm", "zlib"
+ ];
+ }
+
+ const BUILTIN_MODULES = getBuiltinModules();
+
+ const DECL_REQUIRE = "require",
+ DECL_UNINITIALIZED = "uninitialized",
+ DECL_OTHER = "other";
+
+ const REQ_CORE = "core",
+ REQ_FILE = "file",
+ REQ_MODULE = "module",
+ 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}\//.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 = {};
+
+ declarations.forEach(declaration => {
+ const type = getDeclarationType(declaration.init);
+
+ contains[type] = true;
+ });
+
+ return !!(
+ 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 = {};
+
+ declarations.forEach(declaration => {
+ 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, message: "Do not mix 'require' and other declarations." });
+ } else if (grouping && !isGrouped(node.declarations)) {
+ context.report({ node, message: "Do not mix core, module, file and computed requires." });
+ }
+ }
+ };
+
+ }
+};