123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- 'use strict';
- const {ReferenceTracker} = require('eslint-utils');
- const builtins = require('./utils/builtins.js');
- const {
- switchCallExpressionToNewExpression,
- switchNewExpressionToCallExpression,
- } = require('./fix/index.js');
- const messages = {
- enforce: 'Use `new {{name}}()` instead of `{{name}}()`.',
- disallow: 'Use `{{name}}()` instead of `new {{name}}()`.',
- };
- function * enforceNewExpression({sourceCode, tracker}) {
- const traceMap = Object.fromEntries(
- builtins.enforceNew.map(name => [name, {[ReferenceTracker.CALL]: true}]),
- );
- for (const {node, path: [name]} of tracker.iterateGlobalReferences(traceMap)) {
- if (name === 'Object') {
- const {parent} = node;
- if (
- parent.type === 'BinaryExpression'
- && (parent.operator === '===' || parent.operator === '!==')
- && (parent.left === node || parent.right === node)
- ) {
- continue;
- }
- }
- yield {
- node,
- messageId: 'enforce',
- data: {name},
- fix: fixer => switchCallExpressionToNewExpression(node, sourceCode, fixer),
- };
- }
- }
- function * enforceCallExpression({sourceCode, tracker}) {
- const traceMap = Object.fromEntries(
- builtins.disallowNew.map(name => [name, {[ReferenceTracker.CONSTRUCT]: true}]),
- );
- for (const {node, path: [name]} of tracker.iterateGlobalReferences(traceMap)) {
- const problem = {
- node,
- messageId: 'disallow',
- data: {name},
- };
- if (name !== 'String' && name !== 'Boolean' && name !== 'Number') {
- problem.fix = function * (fixer) {
- yield * switchNewExpressionToCallExpression(node, sourceCode, fixer);
- };
- }
- yield problem;
- }
- }
- /** @param {import('eslint').Rule.RuleContext} context */
- const create = context => ({
- * 'Program:exit'() {
- const sourceCode = context.getSourceCode();
- const tracker = new ReferenceTracker(context.getScope());
- yield * enforceNewExpression({sourceCode, tracker});
- yield * enforceCallExpression({sourceCode, tracker});
- },
- });
- /** @type {import('eslint').Rule.RuleModule} */
- module.exports = {
- create,
- meta: {
- type: 'suggestion',
- docs: {
- description: 'Enforce the use of `new` for all builtins, except `String`, `Number`, `Boolean`, `Symbol` and `BigInt`.',
- },
- fixable: 'code',
- messages,
- },
- };
|