eslint-plugin-unicorn
Advanced tools
Comparing version 20.1.0 to 21.0.0
@@ -42,2 +42,3 @@ 'use strict'; | ||
'unicorn/no-null': 'error', | ||
'unicorn/no-object-as-default-parameter': 'error', | ||
'unicorn/no-process-exit': 'error', | ||
@@ -52,5 +53,7 @@ 'unicorn/no-reduce': 'error', | ||
'unicorn/prefer-add-event-listener': 'error', | ||
'unicorn/prefer-array-find': 'error', | ||
'unicorn/prefer-dataset': 'error', | ||
'unicorn/prefer-event-key': 'error', | ||
'unicorn/prefer-flat-map': 'error', | ||
// TODO: Enable this by default when targeting Node.js 12. | ||
'unicorn/prefer-flat-map': 'off', | ||
'unicorn/prefer-includes': 'error', | ||
@@ -57,0 +60,0 @@ 'unicorn/prefer-modern-dom-apis': 'error', |
{ | ||
"name": "eslint-plugin-unicorn", | ||
"version": "20.1.0", | ||
"version": "21.0.0", | ||
"description": "Various awesome ESLint rules", | ||
@@ -40,3 +40,3 @@ "license": "MIT", | ||
"eslint-template-visitor": "^2.0.0", | ||
"eslint-utils": "^2.0.0", | ||
"eslint-utils": "^2.1.0", | ||
"import-modules": "^2.0.0", | ||
@@ -53,21 +53,22 @@ "lodash": "^4.17.15", | ||
"@ava/babel": "^1.0.1", | ||
"@babel/code-frame": "7.10.3", | ||
"@lubien/fixture-beta-package": "^1.0.0-beta.1", | ||
"@typescript-eslint/parser": "^2.33.0", | ||
"ava": "^3.8.2", | ||
"@typescript-eslint/parser": "^3.4.0", | ||
"ava": "^3.9.0", | ||
"babel-eslint": "^10.1.0", | ||
"chalk": "^4.0.0", | ||
"eslint": "^7.0.0", | ||
"chalk": "^4.1.0", | ||
"eslint": "^7.3.0", | ||
"eslint-ava-rule-tester": "^4.0.0", | ||
"eslint-plugin-eslint-plugin": "^2.2.1", | ||
"execa": "^4.0.1", | ||
"eslint-plugin-eslint-plugin": "^2.3.0", | ||
"execa": "^4.0.2", | ||
"listr": "^0.14.3", | ||
"nyc": "^15.0.1", | ||
"nyc": "^15.1.0", | ||
"outdent": "^0.7.1", | ||
"pify": "^5.0.0", | ||
"typescript": "^3.9.2", | ||
"vue-eslint-parser": "^7.0.0", | ||
"xo": "^0.30.0" | ||
"typescript": "^3.9.5", | ||
"vue-eslint-parser": "^7.1.0", | ||
"xo": "^0.32.0" | ||
}, | ||
"peerDependencies": { | ||
"eslint": ">=7.0.0" | ||
"eslint": ">=7.3.0" | ||
}, | ||
@@ -100,2 +101,3 @@ "ava": { | ||
"rules": { | ||
"eslint-plugin/prefer-object-rule": "off", | ||
"eslint-plugin/require-meta-docs-url": "off" | ||
@@ -113,12 +115,5 @@ } | ||
"strict": "error", | ||
"array-callback-return": [ | ||
"error", | ||
{ | ||
"allowImplicit": true | ||
} | ||
], | ||
"unicorn/no-null": "error", | ||
"unicorn/string-content": "off" | ||
"unicorn/no-null": "error" | ||
} | ||
} | ||
} |
@@ -58,2 +58,3 @@ # eslint-plugin-unicorn [![Build Status](https://github.com/sindresorhus/eslint-plugin-unicorn/workflows/CI/badge.svg?branch=master)](https://github.com/sindresorhus/eslint-plugin-unicorn/actions?query=branch%3Amaster+workflow%3ACI) [![Coverage Status](https://codecov.io/gh/sindresorhus/eslint-plugin-unicorn/branch/master/graph/badge.svg)](https://codecov.io/gh/sindresorhus/eslint-plugin-unicorn/branch/master) | ||
"unicorn/no-null": "error", | ||
"unicorn/no-object-as-default-parameter": "error", | ||
"unicorn/no-process-exit": "error", | ||
@@ -68,2 +69,3 @@ "unicorn/no-reduce": "error", | ||
"unicorn/prefer-add-event-listener": "error", | ||
"unicorn/prefer-array-find": "error", | ||
"unicorn/prefer-dataset": "error", | ||
@@ -120,2 +122,3 @@ "unicorn/prefer-event-key": "error", | ||
- [no-null](docs/rules/no-null.md) - Disallow the use of the `null` literal. | ||
- [no-object-as-default-parameter](docs/rules/no-object-as-default-parameter.md) - Disallow the use of objects as default parameters. | ||
- [no-process-exit](docs/rules/no-process-exit.md) - Disallow `process.exit()`. | ||
@@ -130,2 +133,3 @@ - [no-reduce](docs/rules/no-reduce.md) - Disallow `Array#reduce()` and `Array#reduceRight()`. | ||
- [prefer-add-event-listener](docs/rules/prefer-add-event-listener.md) - Prefer `.addEventListener()` and `.removeEventListener()` over `on`-functions. *(partly fixable)* | ||
- [prefer-array-find](docs/rules/prefer-array-find.md) - Prefer `.find(…)` over the first element from `.filter(…)`. *(partly fixable)* | ||
- [prefer-dataset](docs/rules/prefer-dataset.md) - Prefer using `.dataset` on DOM elements over `.setAttribute(…)`. *(fixable)* | ||
@@ -132,0 +136,0 @@ - [prefer-event-key](docs/rules/prefer-event-key.md) - Prefer `KeyboardEvent#key` over `KeyboardEvent#keyCode`. *(partly fixable)* |
'use strict'; | ||
const {getFunctionHeadLocation, getFunctionNameWithKind} = require('eslint-utils'); | ||
const getDocumentationUrl = require('./utils/get-documentation-url'); | ||
const getReferences = require('./utils/get-references'); | ||
const MESSAGE_ID_NAMED = 'named'; | ||
const MESSAGE_ID_ANONYMOUS = 'anonymous'; | ||
const MESSAGE_ID = 'consistent-function-scoping'; | ||
@@ -108,3 +108,4 @@ const isSameScope = (scope1, scope2) => | ||
node.parent && | ||
node.parent.type === 'CallExpression'; | ||
node.parent.type === 'CallExpression' && | ||
node.parent.callee === node; | ||
@@ -167,21 +168,8 @@ function checkNode(node, scopeManager) { | ||
if (!hasJsx && !checkNode(node, scopeManager)) { | ||
const functionType = node.type === 'ArrowFunctionExpression' ? 'arrow function' : 'function'; | ||
let functionName = ''; | ||
if (node.id) { | ||
functionName = node.id.name; | ||
} else if ( | ||
node.parent && | ||
node.parent.type === 'VariableDeclarator' && | ||
node.parent.id && | ||
node.parent.id.type === 'Identifier' | ||
) { | ||
functionName = node.parent.id.name; | ||
} | ||
context.report({ | ||
node, | ||
messageId: functionName ? MESSAGE_ID_NAMED : MESSAGE_ID_ANONYMOUS, | ||
loc: getFunctionHeadLocation(node, sourceCode), | ||
messageId: MESSAGE_ID, | ||
data: { | ||
functionType, | ||
functionName | ||
functionNameWithKind: getFunctionNameWithKind(node) | ||
} | ||
@@ -207,6 +195,5 @@ }); | ||
messages: { | ||
[MESSAGE_ID_NAMED]: 'Move {{functionType}} `{{functionName}}` to the outer scope.', | ||
[MESSAGE_ID_ANONYMOUS]: 'Move {{functionType}} to the outer scope.' | ||
[MESSAGE_ID]: 'Move {{functionNameWithKind}} to the outer scope.' | ||
} | ||
} | ||
}; |
@@ -125,21 +125,15 @@ 'use strict'; | ||
message: 'Pass the error message to `super()` instead of setting `this.message`.', | ||
fix: fixer => { | ||
const fixings = []; | ||
* fix(fixer) { | ||
if (superExpression.expression.arguments.length === 0) { | ||
const rhs = expression.expression.right; | ||
fixings.push( | ||
fixer.insertTextAfterRange([ | ||
superExpression.range[0], | ||
superExpression.range[0] + 6 | ||
], rhs.raw || rhs.name) | ||
); | ||
yield fixer.insertTextAfterRange([ | ||
superExpression.range[0], | ||
superExpression.range[0] + 6 | ||
], rhs.raw || rhs.name); | ||
} | ||
fixings.push( | ||
fixer.removeRange([ | ||
messageExpressionIndex === 0 ? constructorBodyNode.range[0] : constructorBody[messageExpressionIndex - 1].range[1], | ||
expression.range[1] | ||
]) | ||
); | ||
return fixings; | ||
yield fixer.removeRange([ | ||
messageExpressionIndex === 0 ? constructorBodyNode.range[0] : constructorBody[messageExpressionIndex - 1].range[1], | ||
expression.range[1] | ||
]); | ||
} | ||
@@ -146,0 +140,0 @@ }); |
@@ -5,2 +5,3 @@ 'use strict'; | ||
const methodSelector = require('./utils/method-selector'); | ||
const {notFunctionSelector} = require('./utils/not-function'); | ||
@@ -131,10 +132,7 @@ const ERROR_WITH_NAME_MESSAGE_ID = 'error-with-name'; | ||
const ignoredFirstArgumentSelector = `:not(${ | ||
[ | ||
'[arguments.0.type="FunctionExpression"]', | ||
'[arguments.0.type="ArrowFunctionExpression"]', | ||
'[arguments.0.type="Literal"]', | ||
'[arguments.0.type="Identifier"][arguments.0.name="undefined"]' | ||
].join(',') | ||
})`; | ||
const ignoredFirstArgumentSelector = [ | ||
notFunctionSelector('arguments.0'), | ||
'[arguments.0.type!="FunctionExpression"]', | ||
'[arguments.0.type!="ArrowFunctionExpression"]' | ||
].join(''); | ||
@@ -141,0 +139,0 @@ const create = context => { |
'use strict'; | ||
const methodSelector = require('./utils/method-selector'); | ||
const getDocumentationUrl = require('./utils/get-documentation-url'); | ||
const {notFunctionSelector} = require('./utils/not-function'); | ||
@@ -8,12 +9,4 @@ const MESSAGE_ID_REDUCE = 'reduce'; | ||
const ignoredFirstArgumentSelector = `:not(${ | ||
[ | ||
'[arguments.0.type="Literal"]', | ||
'[arguments.0.type="Identifier"][arguments.0.name="undefined"]' | ||
].join(',') | ||
})`; | ||
const PROTOTYPE_SELECTOR = [ | ||
methodSelector({names: ['call', 'apply']}), | ||
ignoredFirstArgumentSelector, | ||
const prototypeSelector = method => [ | ||
methodSelector({name: method}), | ||
'[callee.object.type="MemberExpression"]', | ||
@@ -49,5 +42,12 @@ '[callee.object.computed=false]', | ||
const PROTOTYPE_CALL_SELECTOR = [ | ||
prototypeSelector('call'), | ||
notFunctionSelector('arguments.1') | ||
].join(''); | ||
const PROTOTYPE_APPLY_SELECTOR = prototypeSelector('apply'); | ||
const METHOD_SELECTOR = [ | ||
methodSelector({names: ['reduce', 'reduceRight'], min: 1, max: 2}), | ||
ignoredFirstArgumentSelector | ||
notFunctionSelector('arguments.0') | ||
].join(''); | ||
@@ -61,5 +61,9 @@ | ||
}, | ||
[PROTOTYPE_SELECTOR](node) { | ||
[PROTOTYPE_CALL_SELECTOR](node) { | ||
// For cases [].reduce.call() and Array.prototype.reduce.call() | ||
context.report({node: node.callee.object.property, messageId: node.callee.object.property.name}); | ||
}, | ||
[PROTOTYPE_APPLY_SELECTOR](node) { | ||
// For cases [].reduce.apply() and Array.prototype.reduce.apply() | ||
context.report({node: node.callee.object.property, messageId: node.callee.object.property.name}); | ||
} | ||
@@ -66,0 +70,0 @@ }; |
@@ -35,2 +35,39 @@ 'use strict'; | ||
const compareFunctionNames = new Set([ | ||
'is', | ||
'equal', | ||
'notEqual', | ||
'strictEqual', | ||
'notStrictEqual', | ||
'propertyVal', | ||
'notPropertyVal', | ||
'not', | ||
'include', | ||
'property', | ||
'toBe', | ||
'toContain', | ||
'toContainEqual', | ||
'toEqual', | ||
'same', | ||
'notSame', | ||
'strictSame', | ||
'strictNotSame' | ||
]); | ||
const isCompareFunction = node => { | ||
let name; | ||
if (node.type === 'Identifier') { | ||
name = node.name; | ||
} else if ( | ||
node.type === 'MemberExpression' && | ||
node.computed === false && | ||
node.property && | ||
node.property.type === 'Identifier' | ||
) { | ||
name = node.property.name; | ||
} | ||
return compareFunctionNames.has(name); | ||
}; | ||
const create = context => { | ||
@@ -68,2 +105,6 @@ const listener = fix => node => { | ||
CallExpression: node => { | ||
if (isCompareFunction(node.callee)) { | ||
return; | ||
} | ||
const argumentNodes = node.arguments; | ||
@@ -70,0 +111,0 @@ const undefinedArguments = []; |
@@ -100,18 +100,16 @@ 'use strict'; | ||
messageId: MESSAGE_ID_FLATMAP, | ||
fix: fixer => { | ||
const fixings = [ | ||
// Removes: | ||
// map(…).flat(); | ||
// ^^^^^^^ | ||
// (map(…)).flat(); | ||
// ^^^^^^^ | ||
fixer.removeRange([fixStart, fixEnd]), | ||
* fix(fixer) { | ||
// Removes: | ||
// map(…).flat(); | ||
// ^^^^^^^ | ||
// (map(…)).flat(); | ||
// ^^^^^^^ | ||
yield fixer.removeRange([fixStart, fixEnd]); | ||
// Renames: | ||
// map(…).flat(); | ||
// ^^^ | ||
// (map(…)).flat(); | ||
// ^^^ | ||
fixer.replaceText(mapProperty, 'flatMap') | ||
]; | ||
// Renames: | ||
// map(…).flat(); | ||
// ^^^ | ||
// (map(…)).flat(); | ||
// ^^^ | ||
yield fixer.replaceText(mapProperty, 'flatMap'); | ||
@@ -124,7 +122,5 @@ if (hasSemicolon) { | ||
// ^ | ||
fixings.push(fixer.insertTextAfter(beforeSemicolon, ';')); | ||
fixings.push(fixer.remove(maybeSemicolon)); | ||
yield fixer.insertTextAfter(beforeSemicolon, ';'); | ||
yield fixer.remove(maybeSemicolon); | ||
} | ||
return fixings; | ||
} | ||
@@ -131,0 +127,0 @@ }); |
@@ -291,9 +291,9 @@ 'use strict'; | ||
message: `Prefer negative index over length minus index for \`${method}\`.`, | ||
fix(fixer) { | ||
* fix(fixer) { | ||
const sourceCode = context.getSourceCode(); | ||
return removableNodes.map( | ||
node => fixer.removeRange( | ||
for (const node of removableNodes) { | ||
yield fixer.removeRange( | ||
getRemovalRange(node, sourceCode) | ||
) | ||
); | ||
); | ||
} | ||
} | ||
@@ -300,0 +300,0 @@ }); |
@@ -19,3 +19,3 @@ 'use strict'; | ||
const getLiteralFix = (fixer, node, identifierName) => { | ||
function * getLiteralFix(fixer, node, identifierName) { | ||
let replacement = node.raw; | ||
@@ -30,18 +30,14 @@ if (identifierName === 'getElementById') { | ||
return [fixer.replaceText(node, replacement)]; | ||
}; | ||
yield fixer.replaceText(node, replacement); | ||
} | ||
const getTemplateLiteralFix = (fixer, node, identifierName) => { | ||
const fix = [ | ||
fixer.insertTextAfter(node, '`'), | ||
fixer.insertTextBefore(node, '`') | ||
]; | ||
function * getTemplateLiteralFix(fixer, node, identifierName) { | ||
yield fixer.insertTextAfter(node, '`'); | ||
yield fixer.insertTextBefore(node, '`'); | ||
node.quasis.forEach(templateElement => { | ||
for (const templateElement of node.quasis) { | ||
if (identifierName === 'getElementById') { | ||
fix.push( | ||
fixer.replaceText( | ||
templateElement, | ||
getReplacementForId(templateElement.value.cooked) | ||
) | ||
yield fixer.replaceText( | ||
templateElement, | ||
getReplacementForId(templateElement.value.cooked) | ||
); | ||
@@ -51,14 +47,10 @@ } | ||
if (identifierName === 'getElementsByClassName') { | ||
fix.push( | ||
fixer.replaceText( | ||
templateElement, | ||
getReplacementForClass(templateElement.value.cooked) | ||
) | ||
yield fixer.replaceText( | ||
templateElement, | ||
getReplacementForClass(templateElement.value.cooked) | ||
); | ||
} | ||
}); | ||
} | ||
} | ||
return fix; | ||
}; | ||
const canBeFixed = node => { | ||
@@ -94,6 +86,6 @@ if (node.type === 'Literal') { | ||
const getArgumentFix = nodeToBeFixed.type === 'Literal' ? getLiteralFix : getTemplateLiteralFix; | ||
return fixer => [ | ||
...getArgumentFix(fixer, nodeToBeFixed, identifierName), | ||
fixer.replaceText(node.callee.property, preferedSelector) | ||
]; | ||
return function * (fixer) { | ||
yield * getArgumentFix(fixer, nodeToBeFixed, identifierName); | ||
yield fixer.replaceText(node.callee.property, preferedSelector); | ||
}; | ||
}; | ||
@@ -100,0 +92,0 @@ |
@@ -166,7 +166,10 @@ 'use strict'; | ||
}, | ||
fix: fixer => [ | ||
fixer.insertTextBefore(node.parent.init, 'new Set('), | ||
fixer.insertTextAfter(node.parent.init, ')'), | ||
...identifiers.map(identifier => fixer.replaceText(identifier.parent.property, 'has')) | ||
] | ||
* fix(fixer) { | ||
yield fixer.insertTextBefore(node.parent.init, 'new Set('); | ||
yield fixer.insertTextAfter(node.parent.init, ')'); | ||
for (const identifier of identifiers) { | ||
yield fixer.replaceText(identifier.parent.property, 'has'); | ||
} | ||
} | ||
}); | ||
@@ -173,0 +176,0 @@ } |
@@ -14,3 +14,3 @@ 'use strict'; | ||
string, | ||
['^', '$', '+', '[', '{', '(', '\\', '.', '?', '*'] | ||
['^', '$', '+', '[', '{', '(', '\\', '.', '?', '*', '|'] | ||
); | ||
@@ -17,0 +17,0 @@ |
@@ -97,2 +97,5 @@ 'use strict'; | ||
}, | ||
ev: { | ||
event: true | ||
}, | ||
evt: { | ||
@@ -629,5 +632,6 @@ event: true | ||
problem.fix = fixer => { | ||
return getVariableIdentifiers(variable) | ||
.map(identifier => renameIdentifier(identifier, replacement, fixer, sourceCode)); | ||
problem.fix = function * (fixer) { | ||
for (const identifier of getVariableIdentifiers(variable)) { | ||
yield renameIdentifier(identifier, replacement, fixer, sourceCode); | ||
} | ||
}; | ||
@@ -634,0 +638,0 @@ } |
@@ -28,3 +28,3 @@ 'use strict'; | ||
if (name) { | ||
selector.push(`[callee.property.name="${name}"]`); | ||
selector.push(`[${prefix}callee.property.name="${name}"]`); | ||
} | ||
@@ -31,0 +31,0 @@ |
@@ -31,3 +31,3 @@ 'use strict'; | ||
if (identifier.typeAnnotation) { | ||
return fixer.replaceText(identifier, `${name}${sourceCode.getText(identifier.typeAnnotation)}`); | ||
return fixer.replaceText(identifier, `${name}${identifier.optional ? '?' : ''}${sourceCode.getText(identifier.typeAnnotation)}`); | ||
} | ||
@@ -34,0 +34,0 @@ |
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
225538
91
7424
190
18
Updatedeslint-utils@^2.1.0