eslint-plugin-unicorn
Advanced tools
Comparing version 51.0.1 to 52.0.0
@@ -17,2 +17,3 @@ 'use strict'; | ||
'unicorn/no-abusive-eslint-disable': 'error', | ||
'unicorn/no-anonymous-default-export': 'error', | ||
'unicorn/no-array-callback-reference': 'error', | ||
@@ -24,2 +25,3 @@ 'unicorn/no-array-for-each': 'error', | ||
'unicorn/no-await-expression-member': 'error', | ||
'unicorn/no-await-in-promise-methods': 'error', | ||
'unicorn/no-console-spaces': 'error', | ||
@@ -43,2 +45,3 @@ 'unicorn/no-document-cookie': 'error', | ||
'unicorn/no-process-exit': 'error', | ||
'unicorn/no-single-promise-in-promise-methods': 'error', | ||
'unicorn/no-static-only-class': 'error', | ||
@@ -45,0 +48,0 @@ 'unicorn/no-thenable': 'error', |
{ | ||
"name": "eslint-plugin-unicorn", | ||
"version": "51.0.1", | ||
"version": "52.0.0", | ||
"description": "More than 100 powerful ESLint rules", | ||
@@ -81,3 +81,3 @@ "license": "MIT", | ||
"eslint-ava-rule-tester": "^5.0.1", | ||
"eslint-doc-generator": "^1.6.1", | ||
"eslint-doc-generator": "^1.7.0", | ||
"eslint-plugin-eslint-plugin": "^5.2.1", | ||
@@ -138,3 +138,4 @@ "eslint-plugin-internal-rules": "file:./scripts/internal-rules/", | ||
], | ||
"import/order": "off" | ||
"import/order": "off", | ||
"func-names": "off" | ||
}, | ||
@@ -141,0 +142,0 @@ "overrides": [ |
@@ -109,3 +109,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) | ||
🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\ | ||
💡 Manually fixable by [editor suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions). | ||
💡 Manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions). | ||
@@ -128,2 +128,3 @@ | Name | Description | 💼 | 🔧 | 💡 | | ||
| [no-abusive-eslint-disable](docs/rules/no-abusive-eslint-disable.md) | Enforce specifying rules to disable in `eslint-disable` comments. | ✅ | | | | ||
| [no-anonymous-default-export](docs/rules/no-anonymous-default-export.md) | Disallow anonymous functions and classes as the default export. | ✅ | | 💡 | | ||
| [no-array-callback-reference](docs/rules/no-array-callback-reference.md) | Prevent passing a function reference directly to iterator methods. | ✅ | | 💡 | | ||
@@ -135,2 +136,3 @@ | [no-array-for-each](docs/rules/no-array-for-each.md) | Prefer `for…of` over the `forEach` method. | ✅ | 🔧 | 💡 | | ||
| [no-await-expression-member](docs/rules/no-await-expression-member.md) | Disallow member access from await expression. | ✅ | 🔧 | | | ||
| [no-await-in-promise-methods](docs/rules/no-await-in-promise-methods.md) | Disallow using `await` in `Promise` method parameters. | ✅ | | 💡 | | ||
| [no-console-spaces](docs/rules/no-console-spaces.md) | Do not use leading/trailing space between `console.log` parameters. | ✅ | 🔧 | | | ||
@@ -152,2 +154,3 @@ | [no-document-cookie](docs/rules/no-document-cookie.md) | Do not use `document.cookie` directly. | ✅ | | | | ||
| [no-process-exit](docs/rules/no-process-exit.md) | Disallow `process.exit()`. | ✅ | | | | ||
| [no-single-promise-in-promise-methods](docs/rules/no-single-promise-in-promise-methods.md) | Disallow passing single-element arrays to `Promise` methods. | ✅ | 🔧 | 💡 | | ||
| [no-static-only-class](docs/rules/no-static-only-class.md) | Disallow classes that only have static members. | ✅ | 🔧 | | | ||
@@ -154,0 +157,0 @@ | [no-thenable](docs/rules/no-thenable.md) | Disallow `then` property. | ✅ | | | |
@@ -88,3 +88,3 @@ 'use strict'; | ||
function fixFilename(words, caseFunctions, {leading, extension}) { | ||
function fixFilename(words, caseFunctions, {leading, trailing}) { | ||
const replacements = words | ||
@@ -97,5 +97,28 @@ .map(({word, ignored}) => ignored ? [word] : caseFunctions.map(caseFunction => caseFunction(word))); | ||
return [...new Set(combinations.map(parts => `${leading}${parts.join('')}${extension.toLowerCase()}`))]; | ||
return [...new Set(combinations.map(parts => `${leading}${parts.join('')}${trailing}`))]; | ||
} | ||
function getFilenameParts(filenameWithExtension, {multipleFileExtensions}) { | ||
const extension = path.extname(filenameWithExtension); | ||
const filename = path.basename(filenameWithExtension, extension); | ||
const basename = filename + extension; | ||
const parts = { | ||
basename, | ||
filename, | ||
middle: '', | ||
extension, | ||
}; | ||
if (multipleFileExtensions) { | ||
const [firstPart] = filename.split('.'); | ||
Object.assign(parts, { | ||
filename: firstPart, | ||
middle: filename.slice(firstPart.length), | ||
}); | ||
} | ||
return parts; | ||
} | ||
const leadingUnderscoresRegex = /^(?<leading>_+)(?<tailing>.*)$/; | ||
@@ -148,2 +171,3 @@ function splitFilename(filename) { | ||
}); | ||
const multipleFileExtensions = options.multipleFileExtensions !== false; | ||
const chosenCasesFunctions = chosenCases.map(case_ => ignoreNumbers(cases[case_].fn)); | ||
@@ -158,7 +182,10 @@ const filenameWithExtension = context.physicalFilename; | ||
Program() { | ||
const extension = path.extname(filenameWithExtension); | ||
const filename = path.basename(filenameWithExtension, extension); | ||
const base = filename + extension; | ||
const { | ||
basename, | ||
filename, | ||
middle, | ||
extension, | ||
} = getFilenameParts(filenameWithExtension, {multipleFileExtensions}); | ||
if (ignoredByDefault.has(base) || ignore.some(regexp => regexp.test(base))) { | ||
if (ignoredByDefault.has(basename) || ignore.some(regexp => regexp.test(basename))) { | ||
return; | ||
@@ -175,3 +202,3 @@ } | ||
messageId: MESSAGE_ID_EXTENSION, | ||
data: {filename: filename + extension.toLowerCase(), extension}, | ||
data: {filename: filename + middle + extension.toLowerCase(), extension}, | ||
}; | ||
@@ -185,3 +212,3 @@ } | ||
leading, | ||
extension, | ||
trailing: middle + extension.toLowerCase(), | ||
}); | ||
@@ -220,2 +247,5 @@ | ||
}, | ||
multipleFileExtensions: { | ||
type: 'boolean', | ||
}, | ||
}, | ||
@@ -247,2 +277,5 @@ additionalProperties: false, | ||
}, | ||
multipleFileExtensions: { | ||
type: 'boolean', | ||
}, | ||
}, | ||
@@ -249,0 +282,0 @@ additionalProperties: false, |
@@ -120,5 +120,11 @@ 'use strict'; | ||
}, | ||
'node:path': { | ||
default: true, | ||
}, | ||
util: { | ||
named: true, | ||
}, | ||
'node:util': { | ||
named: true, | ||
}, | ||
}; | ||
@@ -125,0 +131,0 @@ |
'use strict'; | ||
const {isParenthesized} = require('@eslint-community/eslint-utils'); | ||
const {isMethodCall} = require('./ast/index.js'); | ||
const {isNodeMatches, isNodeValueNotFunction} = require('./utils/index.js'); | ||
const { | ||
isNodeMatches, | ||
isNodeValueNotFunction, | ||
isParenthesized, | ||
getParenthesizedRange, | ||
getParenthesizedText, | ||
shouldAddParenthesesToCallExpressionCallee, | ||
} = require('./utils/index.js'); | ||
@@ -28,3 +34,3 @@ const ERROR_WITH_NAME_MESSAGE_ID = 'error-with-name'; | ||
method: 'filter', | ||
test: node => !(node.callee.object.type === 'Identifier' && node.callee.object.name === 'Vue'), | ||
shouldIgnoreCallExpression: node => (node.callee.object.type === 'Identifier' && node.callee.object.name === 'Vue'), | ||
ignore: [ | ||
@@ -67,3 +73,3 @@ 'Boolean', | ||
method: 'map', | ||
test: node => !(node.callee.object.type === 'Identifier' && node.callee.object.name === 'types'), | ||
shouldIgnoreCallExpression: node => (node.callee.object.type === 'Identifier' && node.callee.object.name === 'types'), | ||
ignore: [ | ||
@@ -109,3 +115,3 @@ 'String', | ||
returnsUndefined = false, | ||
test, | ||
shouldIgnoreCallExpression, | ||
}) => [method, { | ||
@@ -115,26 +121,30 @@ minParameters, | ||
returnsUndefined, | ||
test(node) { | ||
shouldIgnoreCallExpression(callExpression) { | ||
if ( | ||
method !== 'reduce' | ||
&& method !== 'reduceRight' | ||
&& isAwaitExpressionArgument(node) | ||
&& isAwaitExpressionArgument(callExpression) | ||
) { | ||
return false; | ||
return true; | ||
} | ||
if (isNodeMatches(node.callee.object, ignoredCallee)) { | ||
return false; | ||
if (isNodeMatches(callExpression.callee.object, ignoredCallee)) { | ||
return true; | ||
} | ||
if (node.callee.object.type === 'CallExpression' && isNodeMatches(node.callee.object.callee, ignoredCallee)) { | ||
return false; | ||
if ( | ||
callExpression.callee.object.type === 'CallExpression' | ||
&& isNodeMatches(callExpression.callee.object.callee, ignoredCallee) | ||
) { | ||
return true; | ||
} | ||
const [callback] = node.arguments; | ||
return shouldIgnoreCallExpression?.(callExpression) ?? false; | ||
}, | ||
shouldIgnoreCallback(callback) { | ||
if (callback.type === 'Identifier' && ignore.includes(callback.name)) { | ||
return false; | ||
return true; | ||
} | ||
return !test || test(node); | ||
return false; | ||
}, | ||
@@ -170,5 +180,10 @@ }])); | ||
}, | ||
suggest: [], | ||
}; | ||
if (node.type === 'YieldExpression' || node.type === 'AwaitExpression') { | ||
return problem; | ||
} | ||
problem.suggest = []; | ||
const {parameters, minParameters, returnsUndefined} = options; | ||
@@ -186,12 +201,16 @@ for (let parameterLength = minParameters; parameterLength <= parameters.length; parameterLength++) { | ||
const {sourceCode} = context; | ||
let nodeText = sourceCode.getText(node); | ||
if (isParenthesized(node, sourceCode) || type === 'ConditionalExpression') { | ||
nodeText = `(${nodeText})`; | ||
let text = getParenthesizedText(node, sourceCode); | ||
if ( | ||
!isParenthesized(node, sourceCode) | ||
&& shouldAddParenthesesToCallExpressionCallee(node) | ||
) { | ||
text = `(${text})`; | ||
} | ||
return fixer.replaceText( | ||
node, | ||
return fixer.replaceTextRange( | ||
getParenthesizedRange(node, sourceCode), | ||
returnsUndefined | ||
? `(${suggestionParameters}) => { ${nodeText}(${suggestionParameters}); }` | ||
: `(${suggestionParameters}) => ${nodeText}(${suggestionParameters})`, | ||
? `(${suggestionParameters}) => { ${text}(${suggestionParameters}); }` | ||
: `(${suggestionParameters}) => ${text}(${suggestionParameters})`, | ||
); | ||
@@ -207,7 +226,17 @@ }, | ||
function * getTernaryConsequentAndALternate(node) { | ||
if (node.type === 'ConditionalExpression') { | ||
yield * getTernaryConsequentAndALternate(node.consequent); | ||
yield * getTernaryConsequentAndALternate(node.alternate); | ||
return; | ||
} | ||
yield node; | ||
} | ||
/** @param {import('eslint').Rule.RuleContext} context */ | ||
const create = context => ({ | ||
CallExpression(node) { | ||
* CallExpression(callExpression) { | ||
if ( | ||
!isMethodCall(node, { | ||
!isMethodCall(callExpression, { | ||
minimumArguments: 1, | ||
@@ -219,3 +248,3 @@ maximumArguments: 2, | ||
}) | ||
|| node.callee.property.type !== 'Identifier' | ||
|| callExpression.callee.property.type !== 'Identifier' | ||
) { | ||
@@ -225,3 +254,3 @@ return; | ||
const methodNode = node.callee.property; | ||
const methodNode = callExpression.callee.property; | ||
const methodName = methodNode.name; | ||
@@ -232,21 +261,21 @@ if (!iteratorMethods.has(methodName)) { | ||
const [callback] = node.arguments; | ||
if ( | ||
callback.type === 'FunctionExpression' | ||
|| callback.type === 'ArrowFunctionExpression' | ||
// Ignore all `CallExpression`s include `function.bind()` | ||
|| callback.type === 'CallExpression' | ||
|| isNodeValueNotFunction(callback) | ||
) { | ||
const options = iteratorMethods.get(methodName); | ||
if (options.shouldIgnoreCallExpression(callExpression)) { | ||
return; | ||
} | ||
const options = iteratorMethods.get(methodName); | ||
for (const callback of getTernaryConsequentAndALternate(callExpression.arguments[0])) { | ||
if ( | ||
callback.type === 'FunctionExpression' | ||
|| callback.type === 'ArrowFunctionExpression' | ||
// Ignore all `CallExpression`s include `function.bind()` | ||
|| callback.type === 'CallExpression' | ||
|| options.shouldIgnoreCallback(callback) | ||
|| isNodeValueNotFunction(callback) | ||
) { | ||
continue; | ||
} | ||
if (!options.test(node)) { | ||
return; | ||
yield getProblem(context, callback, methodName, options); | ||
} | ||
return getProblem(context, callback, methodName, options); | ||
}, | ||
@@ -253,0 +282,0 @@ }); |
@@ -7,3 +7,2 @@ 'use strict'; | ||
const {removeParentheses} = require('./fix/index.js'); | ||
const shouldAddParenthesesToSpreadElementArgument = require('./utils/should-add-parentheses-to-spread-element-argument.js'); | ||
@@ -49,3 +48,3 @@ const MESSAGE_ID = 'no-useless-fallback-in-spread'; | ||
isLeftObjectParenthesized | ||
|| !shouldAddParenthesesToSpreadElementArgument(left) | ||
|| left.type !== 'SequenceExpression' | ||
) { | ||
@@ -52,0 +51,0 @@ yield * removeParentheses(logicalExpression, fixer, sourceCode); |
@@ -21,2 +21,3 @@ 'use strict'; | ||
const ERROR_POP = 'error-pop'; | ||
const ERROR_AT_ZERO = 'error-at-zero'; | ||
const ERROR_AT_MINUS_ONE = 'error-at-minus-one'; | ||
@@ -31,2 +32,3 @@ const ERROR_DESTRUCTURING_DECLARATION = 'error-destructuring-declaration'; | ||
[ERROR_ZERO_INDEX]: 'Prefer `.find(…)` over `.filter(…)[0]`.', | ||
[ERROR_AT_ZERO]: 'Prefer `.find(…)` over `.filter(…).at(0)`.', | ||
[ERROR_SHIFT]: 'Prefer `.find(…)` over `.filter(…).shift()`.', | ||
@@ -340,2 +342,28 @@ [ERROR_POP]: 'Prefer `.findLast(…)` over `.filter(…).pop()`.', | ||
// `array.filter().at(0)` | ||
context.on('CallExpression', node => { | ||
if (!( | ||
isMethodCall(node, { | ||
method: 'at', | ||
argumentsLength: 1, | ||
optionalCall: false, | ||
optionalMember: false, | ||
}) | ||
&& node.arguments[0].type === 'Literal' | ||
&& node.arguments[0].raw === '0' | ||
&& isArrayFilterCall(node.callee.object) | ||
)) { | ||
return; | ||
} | ||
return { | ||
node: node.callee.object.callee.property, | ||
messageId: ERROR_AT_ZERO, | ||
fix: fixer => [ | ||
fixer.replaceText(node.callee.object.callee.property, 'find'), | ||
...removeMethodCall(fixer, node, sourceCode), | ||
], | ||
}; | ||
}); | ||
if (!checkFromLast) { | ||
@@ -342,0 +370,0 @@ return; |
'use strict'; | ||
const {getPropertyName} = require('@eslint-community/eslint-utils'); | ||
const {getPropertyName, ReferenceTracker} = require('@eslint-community/eslint-utils'); | ||
const {fixSpaceAroundKeyword} = require('./fix/index.js'); | ||
@@ -11,64 +11,107 @@ const {isMemberExpression, isMethodCall} = require('./ast/index.js'); | ||
/** @param {import('eslint').Rule.RuleContext} context */ | ||
function create(context) { | ||
const OBJECT_PROTOTYPE_METHODS = [ | ||
'hasOwnProperty', | ||
'isPrototypeOf', | ||
'propertyIsEnumerable', | ||
'toLocaleString', | ||
'toString', | ||
'valueOf', | ||
]; | ||
function getConstructorAndMethodName(methodNode, {sourceCode, globalReferences}) { | ||
if (!methodNode) { | ||
return; | ||
} | ||
const isGlobalReference = globalReferences.has(methodNode); | ||
if (isGlobalReference) { | ||
const path = globalReferences.get(methodNode); | ||
return { | ||
isGlobalReference: true, | ||
constructorName: 'Object', | ||
methodName: path.at(-1), | ||
}; | ||
} | ||
if (!isMemberExpression(methodNode, {optional: false})) { | ||
return; | ||
} | ||
const objectNode = methodNode.object; | ||
if (!( | ||
(objectNode.type === 'ArrayExpression' && objectNode.elements.length === 0) | ||
|| (objectNode.type === 'ObjectExpression' && objectNode.properties.length === 0) | ||
)) { | ||
return; | ||
} | ||
const constructorName = objectNode.type === 'ArrayExpression' ? 'Array' : 'Object'; | ||
const methodName = getPropertyName(methodNode, sourceCode.getScope(methodNode)); | ||
return { | ||
CallExpression(callExpression) { | ||
let methodNode; | ||
constructorName, | ||
methodName, | ||
}; | ||
} | ||
if ( | ||
// `Reflect.apply([].foo, …)` | ||
// `Reflect.apply({}.foo, …)` | ||
isMethodCall(callExpression, { | ||
object: 'Reflect', | ||
method: 'apply', | ||
minimumArguments: 1, | ||
optionalCall: false, | ||
optionalMember: false, | ||
}) | ||
) { | ||
methodNode = callExpression.arguments[0]; | ||
} else if ( | ||
// `[].foo.{apply,bind,call}(…)` | ||
// `({}).foo.{apply,bind,call}(…)` | ||
isMethodCall(callExpression, { | ||
methods: ['apply', 'bind', 'call'], | ||
optionalCall: false, | ||
optionalMember: false, | ||
}) | ||
) { | ||
methodNode = callExpression.callee.object; | ||
} | ||
function getProblem(callExpression, {sourceCode, globalReferences}) { | ||
let methodNode; | ||
if (!methodNode || !isMemberExpression(methodNode, {optional: false})) { | ||
return; | ||
} | ||
if ( | ||
// `Reflect.apply([].foo, …)` | ||
// `Reflect.apply({}.foo, …)` | ||
isMethodCall(callExpression, { | ||
object: 'Reflect', | ||
method: 'apply', | ||
minimumArguments: 1, | ||
optionalCall: false, | ||
optionalMember: false, | ||
}) | ||
) { | ||
methodNode = callExpression.arguments[0]; | ||
} else if ( | ||
// `[].foo.{apply,bind,call}(…)` | ||
// `({}).foo.{apply,bind,call}(…)` | ||
isMethodCall(callExpression, { | ||
methods: ['apply', 'bind', 'call'], | ||
optionalCall: false, | ||
optionalMember: false, | ||
}) | ||
) { | ||
methodNode = callExpression.callee.object; | ||
} | ||
const objectNode = methodNode.object; | ||
const { | ||
isGlobalReference, | ||
constructorName, | ||
methodName, | ||
} = getConstructorAndMethodName(methodNode, {sourceCode, globalReferences}) ?? {}; | ||
if (!( | ||
(objectNode.type === 'ArrayExpression' && objectNode.elements.length === 0) | ||
|| (objectNode.type === 'ObjectExpression' && objectNode.properties.length === 0) | ||
)) { | ||
if (!constructorName) { | ||
return; | ||
} | ||
return { | ||
node: methodNode, | ||
messageId: methodName ? 'known-method' : 'unknown-method', | ||
data: {constructorName, methodName}, | ||
* fix(fixer) { | ||
if (isGlobalReference) { | ||
yield fixer.replaceText(methodNode, `${constructorName}.prototype.${methodName}`); | ||
return; | ||
} | ||
const constructorName = objectNode.type === 'ArrayExpression' ? 'Array' : 'Object'; | ||
const {sourceCode} = context; | ||
const methodName = getPropertyName(methodNode, sourceCode.getScope(methodNode)); | ||
if (isMemberExpression(methodNode)) { | ||
const objectNode = methodNode.object; | ||
return { | ||
node: methodNode, | ||
messageId: methodName ? 'known-method' : 'unknown-method', | ||
data: {constructorName, methodName}, | ||
* fix(fixer) { | ||
yield fixer.replaceText(objectNode, `${constructorName}.prototype`); | ||
yield fixer.replaceText(objectNode, `${constructorName}.prototype`); | ||
if ( | ||
objectNode.type === 'ArrayExpression' | ||
|| objectNode.type === 'ObjectExpression' | ||
) { | ||
yield * fixSpaceAroundKeyword(fixer, callExpression, sourceCode); | ||
} | ||
}, | ||
}; | ||
if ( | ||
objectNode.type === 'ArrayExpression' | ||
|| objectNode.type === 'ObjectExpression' | ||
) { | ||
yield * fixSpaceAroundKeyword(fixer, callExpression, sourceCode); | ||
} | ||
} | ||
}, | ||
@@ -78,2 +121,31 @@ }; | ||
/** @param {import('eslint').Rule.RuleContext} context */ | ||
function create(context) { | ||
const {sourceCode} = context; | ||
const callExpressions = []; | ||
context.on('CallExpression', callExpression => { | ||
callExpressions.push(callExpression); | ||
}); | ||
context.on('Program:exit', function * (program) { | ||
const globalReferences = new WeakMap(); | ||
const tracker = new ReferenceTracker(sourceCode.getScope(program)); | ||
for (const {node, path} of tracker.iterateGlobalReferences( | ||
Object.fromEntries(OBJECT_PROTOTYPE_METHODS.map(method => [method, {[ReferenceTracker.READ]: true}])), | ||
)) { | ||
globalReferences.set(node, path); | ||
} | ||
for (const callExpression of callExpressions) { | ||
yield getProblem(callExpression, { | ||
sourceCode, | ||
globalReferences, | ||
}); | ||
} | ||
}); | ||
} | ||
/** @type {import('eslint').Rule.RuleModule} */ | ||
@@ -80,0 +152,0 @@ module.exports = { |
'use strict'; | ||
const {isParenthesized, getStaticValue, isCommaToken, hasSideEffect} = require('@eslint-community/eslint-utils'); | ||
const {getStaticValue, isCommaToken, hasSideEffect} = require('@eslint-community/eslint-utils'); | ||
const { | ||
@@ -7,5 +7,5 @@ getParenthesizedRange, | ||
needsSemicolon, | ||
shouldAddParenthesesToSpreadElementArgument, | ||
isNodeMatches, | ||
isMethodNamed, | ||
hasOptionalChainElement, | ||
} = require('./utils/index.js'); | ||
@@ -93,9 +93,2 @@ const {removeMethodCall} = require('./fix/index.js'); | ||
if (isSpreadable) { | ||
if ( | ||
!isParenthesized(node, sourceCode) | ||
&& shouldAddParenthesesToSpreadElementArgument(node) | ||
) { | ||
text = `(${text})`; | ||
} | ||
text = `...${text}`; | ||
@@ -222,11 +215,4 @@ } | ||
const [start, end] = getParenthesizedRange(object, sourceCode); | ||
let text = sourceCode.text.slice(start, end); | ||
const text = sourceCode.text.slice(start, end); | ||
if ( | ||
!isParenthesized(object, sourceCode) | ||
&& shouldAddParenthesesToSpreadElementArgument(object) | ||
) { | ||
text = `(${text})`; | ||
} | ||
return `[...${text}]`; | ||
@@ -424,3 +410,4 @@ } | ||
}) | ||
&& node.callee.object.type !== 'ArrayExpression' | ||
&& !isArrayLiteral(node.callee.object) | ||
&& !hasOptionalChainElement(node.callee.object) | ||
)) { | ||
@@ -498,3 +485,3 @@ return; | ||
hasSameResult = resultBySplit.length === resultBySpread.length | ||
&& resultBySplit.every((character, index) => character === resultBySpread[index]); | ||
&& resultBySplit.every((character, index) => character === resultBySpread[index]); | ||
} | ||
@@ -501,0 +488,0 @@ |
@@ -132,3 +132,3 @@ 'use strict'; | ||
*/ | ||
module.exports = (name, scopes, isSafe = alwaysTrue) => { | ||
module.exports = function avoidCapture(name, scopes, isSafe = alwaysTrue) { | ||
if (!isValidIdentifier(name)) { | ||
@@ -148,1 +148,2 @@ name += '_'; | ||
}; | ||
'use strict'; | ||
module.exports = (combinations, length = Number.POSITIVE_INFINITY) => { | ||
module.exports = function cartesianProductSamples(combinations, length = Number.POSITIVE_INFINITY) { | ||
const total = combinations.reduce((total, {length}) => total * length, 1); | ||
@@ -5,0 +5,0 @@ |
@@ -12,3 +12,3 @@ 'use strict'; | ||
*/ | ||
module.exports = (string, quote = '\'') => { | ||
module.exports = function escapeString(string, quote = '\'') { | ||
/* c8 ignore start */ | ||
@@ -15,0 +15,0 @@ if (typeof string !== 'string') { |
'use strict'; | ||
module.exports = string => string.replaceAll( | ||
const escapeTemplateElementRaw = string => string.replaceAll( | ||
/(?<=(?:^|[^\\])(?:\\\\)*)(?<symbol>(?:`|\$(?={)))/g, | ||
'\\$<symbol>', | ||
); | ||
module.exports = escapeTemplateElementRaw; |
@@ -7,5 +7,5 @@ 'use strict'; | ||
module.exports = filename => { | ||
module.exports = function getDocumentationUrl(filename) { | ||
const ruleName = path.basename(filename, '.js'); | ||
return `${repoUrl}/blob/v${packageJson.version}/docs/rules/${ruleName}.md`; | ||
}; |
'use strict'; | ||
// Get identifiers of given variable | ||
module.exports = ({identifiers, references}) => [...new Set([ | ||
const getVariableIdentifiers = ({identifiers, references}) => [...new Set([ | ||
...identifiers, | ||
...references.map(({identifier}) => identifier), | ||
])]; | ||
module.exports = getVariableIdentifiers; |
'use strict'; | ||
module.exports = (node1, node2) => | ||
const hasSameRange = (node1, node2) => | ||
node1 | ||
@@ -8,1 +8,2 @@ && node2 | ||
&& node1.range[1] === node2.range[1]; | ||
module.exports = hasSameRange; |
@@ -48,3 +48,4 @@ 'use strict'; | ||
shouldAddParenthesesToMemberExpressionObject: require('./should-add-parentheses-to-member-expression-object.js'), | ||
shouldAddParenthesesToSpreadElementArgument: require('./should-add-parentheses-to-spread-element-argument.js'), | ||
shouldAddParenthesesToCallExpressionCallee: require('./should-add-parentheses-to-call-expression-callee.js'), | ||
shouldAddParenthesesToAwaitExpressionArgument: require('./should-add-parentheses-to-await-expression-argument.js'), | ||
singular: require('./singular.js'), | ||
@@ -51,0 +52,0 @@ toLocation: require('./to-location.js'), |
@@ -22,3 +22,2 @@ 'use strict'; | ||
'AwaitExpression', | ||
'LogicalExpression', | ||
'NewExpression', | ||
@@ -25,0 +24,0 @@ 'TaggedTemplateExpression', |
'use strict'; | ||
module.exports = (node, object, method) => { | ||
module.exports = function isObjectMethod(node, object, method) { | ||
const {callee} = node; | ||
@@ -4,0 +4,0 @@ return ( |
@@ -5,2 +5,3 @@ 'use strict'; | ||
module.exports = node => isExpressionStatement(node.parent); | ||
const isValueNotUsable = node => isExpressionStatement(node.parent); | ||
module.exports = isValueNotUsable; |
@@ -10,3 +10,3 @@ 'use strict'; | ||
*/ | ||
module.exports = (name, scope) => { | ||
module.exports = function resolveVariableName(name, scope) { | ||
while (scope) { | ||
@@ -13,0 +13,0 @@ const variable = scope.set.get(name); |
@@ -46,2 +46,6 @@ 'use strict'; | ||
for (const problem of problems) { | ||
if (!problem) { | ||
continue; | ||
} | ||
if (problem.fix) { | ||
@@ -48,0 +52,0 @@ problem.fix = wrapFixFunction(problem.fix); |
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
676536
217
21389
360