eslint-plugin-unicorn
Advanced tools
Comparing version 53.0.0 to 54.0.0
17
index.js
@@ -50,5 +50,8 @@ 'use strict'; | ||
const createConfig = (rules, isLegacyConfig = false) => ({ | ||
...(isLegacyConfig ? legacyConfigBase : flatConfigBase), | ||
plugins: isLegacyConfig ? ['unicorn'] : {unicorn}, | ||
const createConfig = (rules, flatConfigName = false) => ({ | ||
...( | ||
flatConfigName | ||
? {...flatConfigBase, name: flatConfigName, plugins: {unicorn}} | ||
: {...legacyConfigBase, plugins: ['unicorn']} | ||
), | ||
rules: {...externalRules, ...rules}, | ||
@@ -69,8 +72,8 @@ }); | ||
const configs = { | ||
recommended: createConfig(recommendedRules, /* isLegacyConfig */ true), | ||
all: createConfig(allRules, /* isLegacyConfig */ true), | ||
'flat/recommended': createConfig(recommendedRules), | ||
'flat/all': createConfig(allRules), | ||
recommended: createConfig(recommendedRules), | ||
all: createConfig(allRules), | ||
'flat/recommended': createConfig(recommendedRules, 'unicorn/flat/recommended'), | ||
'flat/all': createConfig(allRules, 'unicorn/flat/all'), | ||
}; | ||
module.exports = {...unicorn, configs}; |
{ | ||
"name": "eslint-plugin-unicorn", | ||
"version": "53.0.0", | ||
"version": "54.0.0", | ||
"description": "More than 100 powerful ESLint rules", | ||
@@ -32,3 +32,3 @@ "license": "MIT", | ||
"run-rules-on-codebase": "node ./test/run-rules-on-codebase/lint.mjs", | ||
"smoke": "eslint-remote-tester --config ./test/smoke/eslint-remote-tester.config.js", | ||
"smoke": "eslint-remote-tester --config ./test/smoke/eslint-remote-tester.config.mjs", | ||
"test": "npm-run-all --continue-on-error lint test:*", | ||
@@ -75,3 +75,3 @@ "test:js": "c8 ava" | ||
"@lubien/fixture-beta-package": "^1.0.0-beta.1", | ||
"@typescript-eslint/parser": "^7.8.0", | ||
"@typescript-eslint/parser": "^8.0.0-alpha.12", | ||
"ava": "^6.1.3", | ||
@@ -86,4 +86,4 @@ "c8": "^9.1.0", | ||
"eslint-plugin-internal-rules": "file:./scripts/internal-rules/", | ||
"eslint-remote-tester": "^3.0.1", | ||
"eslint-remote-tester-repositories": "^1.0.1", | ||
"eslint-remote-tester": "^4.0.0", | ||
"eslint-remote-tester-repositories": "^2.0.0", | ||
"espree": "^10.0.1", | ||
@@ -90,0 +90,0 @@ "execa": "^8.0.1", |
@@ -148,2 +148,3 @@ # eslint-plugin-unicorn [![Coverage Status](https://codecov.io/gh/sindresorhus/eslint-plugin-unicorn/branch/main/graph/badge.svg)](https://codecov.io/gh/sindresorhus/eslint-plugin-unicorn/branch/main) [![npm version](https://img.shields.io/npm/v/eslint-plugin-unicorn.svg?style=flat)](https://npmjs.com/package/eslint-plugin-unicorn) | ||
| [no-negated-condition](docs/rules/no-negated-condition.md) | Disallow negated conditions. | ✅ | 🔧 | | | ||
| [no-negation-in-equality-check](docs/rules/no-negation-in-equality-check.md) | Disallow negated expression in equality check. | ✅ | | 💡 | | ||
| [no-nested-ternary](docs/rules/no-nested-ternary.md) | Disallow nested ternary expressions. | ✅ | 🔧 | | | ||
@@ -179,3 +180,3 @@ | [no-new-array](docs/rules/no-new-array.md) | Disallow `new Array()`. | ✅ | 🔧 | 💡 | | ||
| [prefer-array-index-of](docs/rules/prefer-array-index-of.md) | Prefer `Array#{indexOf,lastIndexOf}()` over `Array#{findIndex,findLastIndex}()` when looking for the index of an item. | ✅ | 🔧 | 💡 | | ||
| [prefer-array-some](docs/rules/prefer-array-some.md) | Prefer `.some(…)` over `.filter(…).length` check and `.{find,findLast}(…)`. | ✅ | 🔧 | 💡 | | ||
| [prefer-array-some](docs/rules/prefer-array-some.md) | Prefer `.some(…)` over `.filter(…).length` check and `.{find,findLast,findIndex,findLastIndex}(…)`. | ✅ | 🔧 | 💡 | | ||
| [prefer-at](docs/rules/prefer-at.md) | Prefer `.at()` method for index access and `String#charAt()`. | ✅ | 🔧 | 💡 | | ||
@@ -192,3 +193,3 @@ | [prefer-blob-reading-methods](docs/rules/prefer-blob-reading-methods.md) | Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(…)` and `Blob#text()` over `FileReader#readAsText(…)`. | ✅ | | | | ||
| [prefer-export-from](docs/rules/prefer-export-from.md) | Prefer `export…from` when re-exporting. | ✅ | 🔧 | 💡 | | ||
| [prefer-includes](docs/rules/prefer-includes.md) | Prefer `.includes()` over `.indexOf()` and `Array#some()` when checking for existence or non-existence. | ✅ | 🔧 | 💡 | | ||
| [prefer-includes](docs/rules/prefer-includes.md) | Prefer `.includes()` over `.indexOf()`, `.lastIndexOf()`, and `Array#some()` when checking for existence or non-existence. | ✅ | 🔧 | 💡 | | ||
| [prefer-json-parse-buffer](docs/rules/prefer-json-parse-buffer.md) | Prefer reading a JSON file as a buffer. | | 🔧 | | | ||
@@ -195,0 +196,0 @@ | [prefer-keyboard-event-key](docs/rules/prefer-keyboard-event-key.md) | Prefer `KeyboardEvent#key` over `KeyboardEvent#keyCode`. | ✅ | 🔧 | | |
@@ -123,2 +123,3 @@ 'use strict'; | ||
// `@typescript-eslint/parse` v7 | ||
// `type Foo = { [Identifier in keyof string]: number; };` | ||
@@ -129,2 +130,8 @@ case 'TSTypeParameter': { | ||
// `@typescript-eslint/parse` v8 | ||
// `type Foo = { [Identifier in keyof string]: number; };` | ||
case 'TSMappedType': { | ||
return parent.key === node; | ||
} | ||
// `type Identifier = Foo` | ||
@@ -131,0 +138,0 @@ case 'TSTypeAliasDeclaration': { |
'use strict'; | ||
const {isParenthesized} = require('../utils/parentheses.js'); | ||
const shouldAddParenthesesToNewExpressionCallee = require('../utils/should-add-parentheses-to-new-expression-callee.js'); | ||
const fixSpaceAroundKeyword = require('./fix-space-around-keywords.js'); | ||
function * switchCallExpressionToNewExpression(node, sourceCode, fixer) { | ||
yield * fixSpaceAroundKeyword(fixer, node, sourceCode); | ||
yield fixer.insertTextBefore(node, 'new '); | ||
@@ -7,0 +9,0 @@ |
@@ -183,3 +183,3 @@ 'use strict'; | ||
} = { | ||
checkFromLast: false, | ||
checkFromLast: true, | ||
...context.options[0], | ||
@@ -432,4 +432,4 @@ }; | ||
type: 'boolean', | ||
// TODO: Change default value to `true`, or remove the option when targeting Node.js 18. | ||
default: false, | ||
// TODO: Remove the option at some point. | ||
default: true, | ||
}, | ||
@@ -436,0 +436,0 @@ }, |
@@ -49,3 +49,2 @@ 'use strict'; | ||
description: 'Array#flatMap()', | ||
recommended: true, | ||
}; | ||
@@ -104,3 +103,2 @@ | ||
description: 'Array#reduce()', | ||
recommended: true, | ||
}; | ||
@@ -126,3 +124,2 @@ | ||
description: '[].concat()', | ||
recommended: true, | ||
shouldSwitchToArray: node => node.arguments[0].type !== 'SpreadElement', | ||
@@ -163,3 +160,2 @@ }; | ||
description: 'Array.prototype.concat()', | ||
recommended: true, | ||
shouldSwitchToArray: node => node.arguments[1].type !== 'SpreadElement' && node.callee.property.name === 'call', | ||
@@ -166,0 +162,0 @@ }; |
@@ -43,6 +43,10 @@ 'use strict'; | ||
); | ||
const isNegativeOne = node => node.type === 'UnaryExpression' && node.operator === '-' && node.argument && node.argument.type === 'Literal' && node.argument.value === 1; | ||
const isLiteralZero = node => isLiteral(node, 0); | ||
/** @param {import('eslint').Rule.RuleContext} context */ | ||
const create = context => ({ | ||
CallExpression(callExpression) { | ||
const create = context => { | ||
// `.find(…)` | ||
// `.findLast(…)` | ||
context.on('CallExpression', callExpression => { | ||
if (!isMethodCall(callExpression, { | ||
@@ -90,5 +94,58 @@ methods: ['find', 'findLast'], | ||
}; | ||
}, | ||
BinaryExpression(binaryExpression) { | ||
}); | ||
// These operators also used in `prefer-includes`, try to reuse the code in future | ||
// `.{findIndex,findLastIndex}(…) !== -1` | ||
// `.{findIndex,findLastIndex}(…) != -1` | ||
// `.{findIndex,findLastIndex}(…) > -1` | ||
// `.{findIndex,findLastIndex}(…) === -1` | ||
// `.{findIndex,findLastIndex}(…) == -1` | ||
// `.{findIndex,findLastIndex}(…) >= 0` | ||
// `.{findIndex,findLastIndex}(…) < 0` | ||
context.on('BinaryExpression', binaryExpression => { | ||
const {left, right, operator} = binaryExpression; | ||
if (!( | ||
isMethodCall(left, { | ||
methods: ['findIndex', 'findLastIndex'], | ||
argumentsLength: 1, | ||
optionalCall: false, | ||
optionalMember: false, | ||
}) | ||
&& ( | ||
(['!==', '!=', '>', '===', '=='].includes(operator) && isNegativeOne(right)) | ||
|| (['>=', '<'].includes(operator) && isLiteralZero(right)) | ||
) | ||
)) { | ||
return; | ||
} | ||
const methodNode = left.callee.property; | ||
return { | ||
node: methodNode, | ||
messageId: ERROR_ID_ARRAY_SOME, | ||
data: {method: methodNode.name}, | ||
* fix(fixer) { | ||
if (['===', '==', '<'].includes(operator)) { | ||
yield fixer.insertTextBefore(binaryExpression, '!'); | ||
} | ||
yield fixer.replaceText(methodNode, 'some'); | ||
const operatorToken = context.sourceCode.getTokenAfter( | ||
left, | ||
token => token.type === 'Punctuator' && token.value === operator, | ||
); | ||
const [start] = operatorToken.range; | ||
const [, end] = binaryExpression.range; | ||
yield fixer.removeRange([start, end]); | ||
}, | ||
}; | ||
}); | ||
// `.filter(…).length > 0` | ||
// `.filter(…).length !== 0` | ||
context.on('BinaryExpression', binaryExpression => { | ||
if (!( | ||
// We assume the user already follows `unicorn/explicit-length-check`. These are allowed in that rule. | ||
@@ -144,4 +201,4 @@ (binaryExpression.operator === '>' || binaryExpression.operator === '!==') | ||
}; | ||
}, | ||
}); | ||
}); | ||
}; | ||
@@ -154,3 +211,3 @@ /** @type {import('eslint').Rule.RuleModule} */ | ||
docs: { | ||
description: 'Prefer `.some(…)` over `.filter(…).length` check and `.{find,findLast}(…)`.', | ||
description: 'Prefer `.some(…)` over `.filter(…).length` check and `.{find,findLast,findIndex,findLastIndex}(…)`.', | ||
recommended: true, | ||
@@ -157,0 +214,0 @@ }, |
@@ -8,5 +8,5 @@ 'use strict'; | ||
const messages = { | ||
[MESSAGE_ID]: 'Use `.includes()`, rather than `.indexOf()`, when checking for existence.', | ||
[MESSAGE_ID]: 'Use `.includes()`, rather than `.{{method}}()`, when checking for existence.', | ||
}; | ||
// Ignore {_,lodash,underscore}.indexOf | ||
// Ignore `{_,lodash,underscore}.{indexOf,lastIndexOf}` | ||
const ignoredVariables = new Set(['_', 'lodash', 'underscore']); | ||
@@ -34,2 +34,5 @@ const isIgnoredTarget = node => node.type === 'Identifier' && ignoredVariables.has(node.name); | ||
messageId: MESSAGE_ID, | ||
data: { | ||
method: node.left.callee.property.name, | ||
}, | ||
fix(fixer) { | ||
@@ -54,3 +57,3 @@ const replacement = `${isNegativeResult(node) ? '!' : ''}${targetSource}.includes(${argumentsSource.join(', ')})`; | ||
if (!isMethodNamed(left, 'indexOf')) { | ||
if (!isMethodNamed(left, 'indexOf') && !isMethodNamed(left, 'lastIndexOf')) { | ||
return; | ||
@@ -92,3 +95,3 @@ } | ||
docs: { | ||
description: 'Prefer `.includes()` over `.indexOf()` and `Array#some()` when checking for existence or non-existence.', | ||
description: 'Prefer `.includes()` over `.indexOf()`, `.lastIndexOf()`, and `Array#some()` when checking for existence or non-existence.', | ||
recommended: true, | ||
@@ -95,0 +98,0 @@ }, |
@@ -157,3 +157,2 @@ 'use strict'; | ||
description: 'Math.sqrt(…)', | ||
recommended: true, | ||
}, | ||
@@ -160,0 +159,0 @@ * fix(fixer) { |
@@ -50,2 +50,3 @@ 'use strict'; | ||
|| (node.parent.type === 'JSXAttribute' && node.parent.value === node) | ||
|| (node.parent.type === 'TSEnumMember' && (node.parent.initializer === node || node.parent.id === node)) | ||
) { | ||
@@ -52,0 +53,0 @@ return; |
@@ -64,3 +64,2 @@ 'use strict'; | ||
description: 'JSON.parse(JSON.stringify(…))', | ||
recommended: true, | ||
}, | ||
@@ -67,0 +66,0 @@ suggest: [ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
696107
224
22136
366