|
| 1 | +import {isParenthesized, getParenthesizedRange} from './utils/index.js'; |
| 2 | +import { |
| 3 | + isNewExpression, |
| 4 | + isEmptyArrayExpression, |
| 5 | + isEmptyStringLiteral, |
| 6 | + isNullLiteral, |
| 7 | + isUndefined, |
| 8 | +} from './ast/index.js'; |
| 9 | +import {removeParentheses, removeArgument} from './fix/index.js'; |
| 10 | + |
| 11 | +const MESSAGE_ID = 'no-useless-collection-argument'; |
| 12 | +const messages = { |
| 13 | + [MESSAGE_ID]: 'The {{description}} is useless.', |
| 14 | +}; |
| 15 | + |
| 16 | +const getDescription = node => { |
| 17 | + if (isEmptyArrayExpression(node)) { |
| 18 | + return 'empty array'; |
| 19 | + } |
| 20 | + |
| 21 | + if (isEmptyStringLiteral(node)) { |
| 22 | + return 'empty string'; |
| 23 | + } |
| 24 | + |
| 25 | + if (isNullLiteral(node)) { |
| 26 | + return '`null`'; |
| 27 | + } |
| 28 | + |
| 29 | + if (isUndefined(node)) { |
| 30 | + return '`undefined`'; |
| 31 | + } |
| 32 | +}; |
| 33 | + |
| 34 | +const removeFallback = (node, context) => |
| 35 | + // Same code from rules/no-useless-fallback-in-spread.js |
| 36 | + /** @param {import('eslint').Rule.RuleFixer} fixer */ |
| 37 | + function * fix(fixer) { |
| 38 | + const {sourceCode} = context; |
| 39 | + const logicalExpression = node.parent; |
| 40 | + const {left} = logicalExpression; |
| 41 | + const isLeftObjectParenthesized = isParenthesized(left, sourceCode); |
| 42 | + const [, start] = isLeftObjectParenthesized |
| 43 | + ? getParenthesizedRange(left, sourceCode) |
| 44 | + : sourceCode.getRange(left); |
| 45 | + const [, end] = sourceCode.getRange(logicalExpression); |
| 46 | + |
| 47 | + yield fixer.removeRange([start, end]); |
| 48 | + |
| 49 | + if ( |
| 50 | + isLeftObjectParenthesized |
| 51 | + || left.type !== 'SequenceExpression' |
| 52 | + ) { |
| 53 | + yield * removeParentheses(logicalExpression, fixer, sourceCode); |
| 54 | + } |
| 55 | + }; |
| 56 | + |
| 57 | +/** @param {import('eslint').Rule.RuleContext} context */ |
| 58 | +const create = context => ({ |
| 59 | + NewExpression(newExpression) { |
| 60 | + if (!isNewExpression(newExpression, { |
| 61 | + names: ['Set', 'Map', 'WeakSet', 'WeakMap'], |
| 62 | + argumentsLength: 1, |
| 63 | + })) { |
| 64 | + return; |
| 65 | + } |
| 66 | + |
| 67 | + const [iterable] = newExpression.arguments; |
| 68 | + const isCheckingFallback = iterable.type === 'LogicalExpression' && iterable.operator === '??'; |
| 69 | + const node = isCheckingFallback ? iterable.right : iterable; |
| 70 | + const description = getDescription(node); |
| 71 | + |
| 72 | + if (!description) { |
| 73 | + return; |
| 74 | + } |
| 75 | + |
| 76 | + return { |
| 77 | + node, |
| 78 | + messageId: MESSAGE_ID, |
| 79 | + data: {description}, |
| 80 | + fix: isCheckingFallback |
| 81 | + ? removeFallback(node, context) |
| 82 | + : fixer => removeArgument(fixer, node, context.sourceCode), |
| 83 | + }; |
| 84 | + }, |
| 85 | +}); |
| 86 | + |
| 87 | +/** @type {import('eslint').Rule.RuleModule} */ |
| 88 | +const config = { |
| 89 | + create, |
| 90 | + meta: { |
| 91 | + type: 'suggestion', |
| 92 | + docs: { |
| 93 | + description: 'Disallow useless values or fallbacks in `Set`, `Map`, `WeakSet`, or `WeakMap`.', |
| 94 | + recommended: 'unopinionated', |
| 95 | + }, |
| 96 | + fixable: 'code', |
| 97 | + messages, |
| 98 | + }, |
| 99 | +}; |
| 100 | + |
| 101 | +export default config; |
0 commit comments