new-for-builtins.js 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. 'use strict';
  2. const builtins = require('./utils/builtins.js');
  3. const isShadowed = require('./utils/is-shadowed.js');
  4. const {callExpressionSelector, newExpressionSelector} = require('./selectors/index.js');
  5. const {
  6. switchCallExpressionToNewExpression,
  7. switchNewExpressionToCallExpression,
  8. } = require('./fix/index.js');
  9. const messages = {
  10. enforce: 'Use `new {{name}}()` instead of `{{name}}()`.',
  11. disallow: 'Use `{{name}}()` instead of `new {{name}}()`.',
  12. };
  13. /** @param {import('eslint').Rule.RuleContext} context */
  14. const create = context => {
  15. const sourceCode = context.getSourceCode();
  16. return {
  17. [callExpressionSelector(builtins.enforceNew)]: node => {
  18. const {callee, parent} = node;
  19. if (isShadowed(context.getScope(), callee)) {
  20. return;
  21. }
  22. const {name} = callee;
  23. if (
  24. name === 'Object'
  25. && parent
  26. && parent.type === 'BinaryExpression'
  27. && (parent.operator === '===' || parent.operator === '!==')
  28. && (parent.left === node || parent.right === node)
  29. ) {
  30. return;
  31. }
  32. return {
  33. node,
  34. messageId: 'enforce',
  35. data: {name},
  36. fix: fixer => switchCallExpressionToNewExpression(node, sourceCode, fixer),
  37. };
  38. },
  39. [newExpressionSelector(builtins.disallowNew)]: node => {
  40. const {callee} = node;
  41. if (isShadowed(context.getScope(), callee)) {
  42. return;
  43. }
  44. const {name} = callee;
  45. const problem = {
  46. node,
  47. messageId: 'disallow',
  48. data: {name},
  49. };
  50. if (name !== 'String' && name !== 'Boolean' && name !== 'Number') {
  51. problem.fix = function * (fixer) {
  52. yield * switchNewExpressionToCallExpression(node, sourceCode, fixer);
  53. };
  54. }
  55. return problem;
  56. },
  57. };
  58. };
  59. /** @type {import('eslint').Rule.RuleModule} */
  60. module.exports = {
  61. create,
  62. meta: {
  63. type: 'suggestion',
  64. docs: {
  65. description: 'Enforce the use of `new` for all builtins, except `String`, `Number`, `Boolean`, `Symbol` and `BigInt`.',
  66. },
  67. fixable: 'code',
  68. messages,
  69. },
  70. };