Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

no-mixed-requires.js 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /**
  2. * @fileoverview Rule to enforce grouped require statements for Node.JS
  3. * @author Raphael Pigulla
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Rule Definition
  8. //------------------------------------------------------------------------------
  9. module.exports = {
  10. meta: {
  11. type: "suggestion",
  12. docs: {
  13. description: "disallow `require` calls to be mixed with regular variable declarations",
  14. category: "Node.js and CommonJS",
  15. recommended: false,
  16. url: "https://eslint.org/docs/rules/no-mixed-requires"
  17. },
  18. schema: [
  19. {
  20. oneOf: [
  21. {
  22. type: "boolean"
  23. },
  24. {
  25. type: "object",
  26. properties: {
  27. grouping: {
  28. type: "boolean"
  29. },
  30. allowCall: {
  31. type: "boolean"
  32. }
  33. },
  34. additionalProperties: false
  35. }
  36. ]
  37. }
  38. ]
  39. },
  40. create(context) {
  41. const options = context.options[0];
  42. let grouping = false,
  43. allowCall = false;
  44. if (typeof options === "object") {
  45. grouping = options.grouping;
  46. allowCall = options.allowCall;
  47. } else {
  48. grouping = !!options;
  49. }
  50. /**
  51. * Returns the list of built-in modules.
  52. *
  53. * @returns {string[]} An array of built-in Node.js modules.
  54. */
  55. function getBuiltinModules() {
  56. /*
  57. * This list is generated using:
  58. * `require("repl")._builtinLibs.concat('repl').sort()`
  59. * This particular list is as per nodejs v0.12.2 and iojs v0.7.1
  60. */
  61. return [
  62. "assert", "buffer", "child_process", "cluster", "crypto",
  63. "dgram", "dns", "domain", "events", "fs", "http", "https",
  64. "net", "os", "path", "punycode", "querystring", "readline",
  65. "repl", "smalloc", "stream", "string_decoder", "tls", "tty",
  66. "url", "util", "v8", "vm", "zlib"
  67. ];
  68. }
  69. const BUILTIN_MODULES = getBuiltinModules();
  70. const DECL_REQUIRE = "require",
  71. DECL_UNINITIALIZED = "uninitialized",
  72. DECL_OTHER = "other";
  73. const REQ_CORE = "core",
  74. REQ_FILE = "file",
  75. REQ_MODULE = "module",
  76. REQ_COMPUTED = "computed";
  77. /**
  78. * Determines the type of a declaration statement.
  79. * @param {ASTNode} initExpression The init node of the VariableDeclarator.
  80. * @returns {string} The type of declaration represented by the expression.
  81. */
  82. function getDeclarationType(initExpression) {
  83. if (!initExpression) {
  84. // "var x;"
  85. return DECL_UNINITIALIZED;
  86. }
  87. if (initExpression.type === "CallExpression" &&
  88. initExpression.callee.type === "Identifier" &&
  89. initExpression.callee.name === "require"
  90. ) {
  91. // "var x = require('util');"
  92. return DECL_REQUIRE;
  93. }
  94. if (allowCall &&
  95. initExpression.type === "CallExpression" &&
  96. initExpression.callee.type === "CallExpression"
  97. ) {
  98. // "var x = require('diagnose')('sub-module');"
  99. return getDeclarationType(initExpression.callee);
  100. }
  101. if (initExpression.type === "MemberExpression") {
  102. // "var x = require('glob').Glob;"
  103. return getDeclarationType(initExpression.object);
  104. }
  105. // "var x = 42;"
  106. return DECL_OTHER;
  107. }
  108. /**
  109. * Determines the type of module that is loaded via require.
  110. * @param {ASTNode} initExpression The init node of the VariableDeclarator.
  111. * @returns {string} The module type.
  112. */
  113. function inferModuleType(initExpression) {
  114. if (initExpression.type === "MemberExpression") {
  115. // "var x = require('glob').Glob;"
  116. return inferModuleType(initExpression.object);
  117. }
  118. if (initExpression.arguments.length === 0) {
  119. // "var x = require();"
  120. return REQ_COMPUTED;
  121. }
  122. const arg = initExpression.arguments[0];
  123. if (arg.type !== "Literal" || typeof arg.value !== "string") {
  124. // "var x = require(42);"
  125. return REQ_COMPUTED;
  126. }
  127. if (BUILTIN_MODULES.indexOf(arg.value) !== -1) {
  128. // "var fs = require('fs');"
  129. return REQ_CORE;
  130. }
  131. if (/^\.{0,2}\//.test(arg.value)) {
  132. // "var utils = require('./utils');"
  133. return REQ_FILE;
  134. }
  135. // "var async = require('async');"
  136. return REQ_MODULE;
  137. }
  138. /**
  139. * Check if the list of variable declarations is mixed, i.e. whether it
  140. * contains both require and other declarations.
  141. * @param {ASTNode} declarations The list of VariableDeclarators.
  142. * @returns {boolean} True if the declarations are mixed, false if not.
  143. */
  144. function isMixed(declarations) {
  145. const contains = {};
  146. declarations.forEach(declaration => {
  147. const type = getDeclarationType(declaration.init);
  148. contains[type] = true;
  149. });
  150. return !!(
  151. contains[DECL_REQUIRE] &&
  152. (contains[DECL_UNINITIALIZED] || contains[DECL_OTHER])
  153. );
  154. }
  155. /**
  156. * Check if all require declarations in the given list are of the same
  157. * type.
  158. * @param {ASTNode} declarations The list of VariableDeclarators.
  159. * @returns {boolean} True if the declarations are grouped, false if not.
  160. */
  161. function isGrouped(declarations) {
  162. const found = {};
  163. declarations.forEach(declaration => {
  164. if (getDeclarationType(declaration.init) === DECL_REQUIRE) {
  165. found[inferModuleType(declaration.init)] = true;
  166. }
  167. });
  168. return Object.keys(found).length <= 1;
  169. }
  170. return {
  171. VariableDeclaration(node) {
  172. if (isMixed(node.declarations)) {
  173. context.report({ node, message: "Do not mix 'require' and other declarations." });
  174. } else if (grouping && !isGrouped(node.declarations)) {
  175. context.report({ node, message: "Do not mix core, module, file and computed requires." });
  176. }
  177. }
  178. };
  179. }
  180. };