no-exports-assign.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. /**
  2. * @author Toru Nagashima <https://github.com/mysticatea>
  3. * See LICENSE file in root directory for full license.
  4. */
  5. "use strict"
  6. const { findVariable } = require("eslint-utils")
  7. function isExports(node, scope) {
  8. let variable = null
  9. return (
  10. node != null &&
  11. node.type === "Identifier" &&
  12. node.name === "exports" &&
  13. (variable = findVariable(scope, node)) != null &&
  14. variable.scope.type === "global"
  15. )
  16. }
  17. function isModuleExports(node, scope) {
  18. let variable = null
  19. return (
  20. node != null &&
  21. node.type === "MemberExpression" &&
  22. !node.computed &&
  23. node.object.type === "Identifier" &&
  24. node.object.name === "module" &&
  25. node.property.type === "Identifier" &&
  26. node.property.name === "exports" &&
  27. (variable = findVariable(scope, node.object)) != null &&
  28. variable.scope.type === "global"
  29. )
  30. }
  31. module.exports = {
  32. meta: {
  33. docs: {
  34. description: "disallow the assignment to `exports`",
  35. category: "Possible Errors",
  36. recommended: true,
  37. url:
  38. "https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-exports-assign.md",
  39. },
  40. fixable: null,
  41. messages: {
  42. forbidden:
  43. "Unexpected assignment to 'exports' variable. Use 'module.exports' instead.",
  44. },
  45. schema: [],
  46. type: "problem",
  47. },
  48. create(context) {
  49. return {
  50. AssignmentExpression(node) {
  51. const scope = context.getScope()
  52. if (
  53. !isExports(node.left, scope) ||
  54. // module.exports = exports = {}
  55. (node.parent.type === "AssignmentExpression" &&
  56. node.parent.right === node &&
  57. isModuleExports(node.parent.left, scope)) ||
  58. // exports = module.exports = {}
  59. (node.right.type === "AssignmentExpression" &&
  60. isModuleExports(node.right.left, scope))
  61. ) {
  62. return
  63. }
  64. context.report({ node, messageId: "forbidden" })
  65. },
  66. }
  67. },
  68. }