no-hide-core-modules.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /**
  2. * @author Toru Nagashima
  3. * See LICENSE file in root directory for full license.
  4. *
  5. * @deprecated since v4.2.0
  6. * This rule was based on an invalid assumption.
  7. * No meaning.
  8. */
  9. "use strict"
  10. const path = require("path")
  11. const resolve = require("resolve")
  12. const getPackageJson = require("../util/get-package-json")
  13. const mergeVisitorsInPlace = require("../util/merge-visitors-in-place")
  14. const visitImport = require("../util/visit-import")
  15. const visitRequire = require("../util/visit-require")
  16. const CORE_MODULES = new Set([
  17. "assert",
  18. "buffer",
  19. "child_process",
  20. "cluster",
  21. "console",
  22. "constants",
  23. "crypto",
  24. "dgram",
  25. "dns",
  26. /* "domain", */ "events",
  27. "fs",
  28. "http",
  29. "https",
  30. "module",
  31. "net",
  32. "os",
  33. "path",
  34. /* "punycode", */ "querystring",
  35. "readline",
  36. "repl",
  37. "stream",
  38. "string_decoder",
  39. "timers",
  40. "tls",
  41. "tty",
  42. "url",
  43. "util",
  44. "vm",
  45. "zlib",
  46. ])
  47. const BACK_SLASH = /\\/gu
  48. module.exports = {
  49. meta: {
  50. docs: {
  51. description:
  52. "disallow third-party modules which are hiding core modules",
  53. category: "Possible Errors",
  54. recommended: false,
  55. url:
  56. "https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-hide-core-modules.md",
  57. },
  58. type: "problem",
  59. deprecated: true,
  60. fixable: null,
  61. schema: [
  62. {
  63. type: "object",
  64. properties: {
  65. allow: {
  66. type: "array",
  67. items: { enum: Array.from(CORE_MODULES) },
  68. additionalItems: false,
  69. uniqueItems: true,
  70. },
  71. ignoreDirectDependencies: { type: "boolean" },
  72. ignoreIndirectDependencies: { type: "boolean" },
  73. },
  74. additionalProperties: false,
  75. },
  76. ],
  77. },
  78. create(context) {
  79. if (context.getFilename() === "<input>") {
  80. return {}
  81. }
  82. const filePath = path.resolve(context.getFilename())
  83. const dirPath = path.dirname(filePath)
  84. const packageJson = getPackageJson(filePath)
  85. const deps = new Set(
  86. [].concat(
  87. Object.keys((packageJson && packageJson.dependencies) || {}),
  88. Object.keys((packageJson && packageJson.devDependencies) || {})
  89. )
  90. )
  91. const options = context.options[0] || {}
  92. const allow = options.allow || []
  93. const ignoreDirectDependencies = Boolean(
  94. options.ignoreDirectDependencies
  95. )
  96. const ignoreIndirectDependencies = Boolean(
  97. options.ignoreIndirectDependencies
  98. )
  99. const targets = []
  100. return [
  101. visitImport(context, { includeCore: true }, importTargets =>
  102. targets.push(...importTargets)
  103. ),
  104. visitRequire(context, { includeCore: true }, requireTargets =>
  105. targets.push(...requireTargets)
  106. ),
  107. {
  108. "Program:exit"() {
  109. for (const target of targets.filter(
  110. t =>
  111. CORE_MODULES.has(t.moduleName) &&
  112. t.moduleName === t.name
  113. )) {
  114. const name = target.moduleName
  115. const allowed =
  116. allow.indexOf(name) !== -1 ||
  117. (ignoreDirectDependencies && deps.has(name)) ||
  118. (ignoreIndirectDependencies && !deps.has(name))
  119. if (allowed) {
  120. continue
  121. }
  122. let resolved = ""
  123. try {
  124. resolved = resolve.sync(`${name}/`, {
  125. basedir: dirPath,
  126. })
  127. } catch (_error) {
  128. continue
  129. }
  130. context.report({
  131. node: target.node,
  132. loc: target.node.loc,
  133. message:
  134. "Unexpected import of third-party module '{{name}}'.",
  135. data: {
  136. name: path
  137. .relative(dirPath, resolved)
  138. .replace(BACK_SLASH, "/"),
  139. },
  140. })
  141. }
  142. },
  143. },
  144. ].reduce(
  145. (mergedVisitor, thisVisitor) =>
  146. mergeVisitorsInPlace(mergedVisitor, thisVisitor),
  147. {}
  148. )
  149. },
  150. }