eslint-plugin-unicorn
Advanced tools
Comparing version 44.0.2 to 45.0.0
@@ -43,2 +43,4 @@ 'use strict'; | ||
'unicorn/no-lonely-if': 'error', | ||
'no-negated-condition': 'off', | ||
'unicorn/no-negated-condition': 'error', | ||
'no-nested-ternary': 'off', | ||
@@ -54,2 +56,3 @@ 'unicorn/no-nested-ternary': 'error', | ||
'unicorn/no-this-assignment': 'error', | ||
'unicorn/no-typeof-undefined': 'error', | ||
'unicorn/no-unnecessary-await': 'error', | ||
@@ -106,2 +109,3 @@ 'unicorn/no-unreadable-array-destructuring': 'error', | ||
'unicorn/prefer-set-has': 'error', | ||
'unicorn/prefer-set-size': 'error', | ||
'unicorn/prefer-spread': 'error', | ||
@@ -108,0 +112,0 @@ // TODO: Enable this by default when targeting Node.js 16. |
{ | ||
"name": "eslint-plugin-unicorn", | ||
"version": "44.0.2", | ||
"version": "45.0.0", | ||
"description": "More than 100 powerful ESLint rules", | ||
@@ -17,10 +17,10 @@ "license": "MIT", | ||
"scripts": { | ||
"create-rule": "node ./scripts/create-rule.mjs && npm run generate-rule-notices && npm run generate-rules-table", | ||
"create-rule": "node ./scripts/create-rule.mjs && npm run fix:eslint-docs", | ||
"fix": "run-p --continue-on-error fix:*", | ||
"fix:eslint-docs": "eslint-doc-generator --ignore-deprecated-rules --ignore-config all --rule-doc-title-format desc --url-configs \"https://github.com/sindresorhus/eslint-plugin-unicorn#preset-configs\"", | ||
"fix:js": "npm run lint:js -- --fix", | ||
"fix:md": "npm run lint:md -- --fix", | ||
"generate-rule-notices": "node ./scripts/generate-rule-notices.mjs", | ||
"generate-rules-table": "node ./scripts/generate-rules-table.mjs", | ||
"integration": "node ./test/integration/test.mjs", | ||
"lint": "run-p --continue-on-error lint:*", | ||
"lint:eslint-docs": "npm run fix:eslint-docs -- --check", | ||
"lint:js": "xo", | ||
@@ -51,3 +51,3 @@ "lint:md": "markdownlint \"**/*.md\"", | ||
"@babel/helper-validator-identifier": "^7.19.1", | ||
"ci-info": "^3.4.0", | ||
"ci-info": "^3.6.1", | ||
"clean-regexp": "^1.0.0", | ||
@@ -58,2 +58,3 @@ "eslint-utils": "^3.0.0", | ||
"is-builtin-module": "^3.2.0", | ||
"jsesc": "3.0.2", | ||
"lodash": "^4.17.21", | ||
@@ -63,4 +64,5 @@ "pluralize": "^8.0.0", | ||
"regexp-tree": "^0.1.24", | ||
"regjsparser": "0.9.1", | ||
"safe-regex": "^2.1.1", | ||
"semver": "^7.3.7", | ||
"semver": "^7.3.8", | ||
"strip-indent": "^3.0.0" | ||
@@ -70,16 +72,17 @@ }, | ||
"@babel/code-frame": "^7.18.6", | ||
"@babel/core": "^7.19.1", | ||
"@babel/core": "^7.20.2", | ||
"@babel/eslint-parser": "^7.19.1", | ||
"@lubien/fixture-beta-package": "^1.0.0-beta.1", | ||
"@typescript-eslint/parser": "^5.37.0", | ||
"@typescript-eslint/parser": "^5.43.0", | ||
"ava": "^3.15.0", | ||
"c8": "^7.12.0", | ||
"chalk": "^5.0.1", | ||
"chalk": "^5.1.2", | ||
"enquirer": "^2.3.6", | ||
"eslint": "^8.23.1", | ||
"eslint": "^8.28.0", | ||
"eslint-ava-rule-tester": "^4.0.0", | ||
"eslint-doc-generator": "^0.24.0", | ||
"eslint-plugin-eslint-plugin": "^5.0.6", | ||
"eslint-plugin-internal-rules": "file:./scripts/internal-rules/", | ||
"eslint-remote-tester": "^3.0.0", | ||
"eslint-remote-tester-repositories": "^0.0.6", | ||
"eslint-remote-tester-repositories": "^0.0.7", | ||
"execa": "^6.1.0", | ||
@@ -93,9 +96,9 @@ "listr": "^0.14.3", | ||
"outdent": "^0.8.0", | ||
"typescript": "^4.8.3", | ||
"typescript": "^4.9.3", | ||
"vue-eslint-parser": "^9.1.0", | ||
"xo": "^0.52.3", | ||
"yaml": "^1.10.2" | ||
"xo": "^0.53.1", | ||
"yaml": "^2.1.3" | ||
}, | ||
"peerDependencies": { | ||
"eslint": ">=8.23.1" | ||
"eslint": ">=8.28.0" | ||
}, | ||
@@ -102,0 +105,0 @@ "ava": { |
235
readme.md
@@ -46,120 +46,125 @@ # 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) | ||
Each rule has emojis denoting: | ||
<!-- Do not manually modify this list. Run: `npm run fix:eslint-docs` --> | ||
<!-- begin auto-generated rules list --> | ||
- ✅ if it belongs to the `recommended` configuration | ||
- 🔧 if some problems reported by the rule are automatically fixable by the `--fix` [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) option | ||
- 💡 if some problems reported by the rule are manually fixable by editor [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions) | ||
💼 [Configurations](https://github.com/sindresorhus/eslint-plugin-unicorn#preset-configs) enabled in.\ | ||
🚫 [Configurations](https://github.com/sindresorhus/eslint-plugin-unicorn#preset-configs) disabled in.\ | ||
✅ Set in the `recommended` [configuration](https://github.com/sindresorhus/eslint-plugin-unicorn#preset-configs).\ | ||
🔧 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). | ||
<!-- Do not manually modify RULES_TABLE part. Run: `npm run generate-rules-table` --> | ||
<!-- RULES_TABLE --> | ||
| Name | Description | ✅ | 🔧 | 💡 | | ||
| :-- | :-- | :-- | :-- | :-- | | ||
| [better-regex](docs/rules/better-regex.md) | Improve regexes by making them shorter, consistent, and safer. | ✅ | 🔧 | | | ||
| [catch-error-name](docs/rules/catch-error-name.md) | Enforce a specific parameter name in catch clauses. | ✅ | 🔧 | | | ||
| [consistent-destructuring](docs/rules/consistent-destructuring.md) | Use destructured variables over properties. | ✅ | 🔧 | 💡 | | ||
| [consistent-function-scoping](docs/rules/consistent-function-scoping.md) | Move function definitions to the highest possible scope. | ✅ | | | | ||
| [custom-error-definition](docs/rules/custom-error-definition.md) | Enforce correct `Error` subclassing. | | 🔧 | | | ||
| [empty-brace-spaces](docs/rules/empty-brace-spaces.md) | Enforce no spaces between braces. | ✅ | 🔧 | | | ||
| [error-message](docs/rules/error-message.md) | Enforce passing a `message` value when creating a built-in error. | ✅ | | | | ||
| [escape-case](docs/rules/escape-case.md) | Require escape sequences to use uppercase values. | ✅ | 🔧 | | | ||
| [expiring-todo-comments](docs/rules/expiring-todo-comments.md) | Add expiration conditions to TODO comments. | ✅ | | | | ||
| [explicit-length-check](docs/rules/explicit-length-check.md) | Enforce explicitly comparing the `length` or `size` property of a value. | ✅ | 🔧 | 💡 | | ||
| [filename-case](docs/rules/filename-case.md) | Enforce a case style for filenames. | ✅ | | | | ||
| [import-style](docs/rules/import-style.md) | Enforce specific import styles per module. | ✅ | | | | ||
| [new-for-builtins](docs/rules/new-for-builtins.md) | Enforce the use of `new` for all builtins, except `String`, `Number`, `Boolean`, `Symbol` and `BigInt`. | ✅ | 🔧 | | | ||
| [no-abusive-eslint-disable](docs/rules/no-abusive-eslint-disable.md) | Enforce specifying rules to disable in `eslint-disable` comments. | ✅ | | | | ||
| [no-array-callback-reference](docs/rules/no-array-callback-reference.md) | Prevent passing a function reference directly to iterator methods. | ✅ | | 💡 | | ||
| [no-array-for-each](docs/rules/no-array-for-each.md) | Prefer `for…of` over the `forEach` method. | ✅ | 🔧 | 💡 | | ||
| [no-array-method-this-argument](docs/rules/no-array-method-this-argument.md) | Disallow using the `this` argument in array methods. | ✅ | 🔧 | 💡 | | ||
| [no-array-push-push](docs/rules/no-array-push-push.md) | Enforce combining multiple `Array#push()` into one call. | ✅ | 🔧 | 💡 | | ||
| [no-array-reduce](docs/rules/no-array-reduce.md) | Disallow `Array#reduce()` and `Array#reduceRight()`. | ✅ | | | | ||
| [no-await-expression-member](docs/rules/no-await-expression-member.md) | Disallow member access from await expression. | ✅ | 🔧 | | | ||
| [no-console-spaces](docs/rules/no-console-spaces.md) | Do not use leading/trailing space between `console.log` parameters. | ✅ | 🔧 | | | ||
| [no-document-cookie](docs/rules/no-document-cookie.md) | Do not use `document.cookie` directly. | ✅ | | | | ||
| [no-empty-file](docs/rules/no-empty-file.md) | Disallow empty files. | ✅ | | | | ||
| [no-for-loop](docs/rules/no-for-loop.md) | Do not use a `for` loop that can be replaced with a `for-of` loop. | ✅ | 🔧 | | | ||
| [no-hex-escape](docs/rules/no-hex-escape.md) | Enforce the use of Unicode escapes instead of hexadecimal escapes. | ✅ | 🔧 | | | ||
| [no-instanceof-array](docs/rules/no-instanceof-array.md) | Require `Array.isArray()` instead of `instanceof Array`. | ✅ | 🔧 | | | ||
| [no-invalid-remove-event-listener](docs/rules/no-invalid-remove-event-listener.md) | Prevent calling `EventTarget#removeEventListener()` with the result of an expression. | ✅ | | | | ||
| [no-keyword-prefix](docs/rules/no-keyword-prefix.md) | Disallow identifiers starting with `new` or `class`. | | | | | ||
| [no-lonely-if](docs/rules/no-lonely-if.md) | Disallow `if` statements as the only statement in `if` blocks without `else`. | ✅ | 🔧 | | | ||
| [no-nested-ternary](docs/rules/no-nested-ternary.md) | Disallow nested ternary expressions. | ✅ | 🔧 | | | ||
| [no-new-array](docs/rules/no-new-array.md) | Disallow `new Array()`. | ✅ | 🔧 | 💡 | | ||
| [no-new-buffer](docs/rules/no-new-buffer.md) | Enforce the use of `Buffer.from()` and `Buffer.alloc()` instead of the deprecated `new Buffer()`. | ✅ | 🔧 | 💡 | | ||
| [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()`. | ✅ | | | | ||
| [no-static-only-class](docs/rules/no-static-only-class.md) | Disallow classes that only have static members. | ✅ | 🔧 | | | ||
| [no-thenable](docs/rules/no-thenable.md) | Disallow `then` property. | ✅ | | | | ||
| [no-this-assignment](docs/rules/no-this-assignment.md) | Disallow assigning `this` to a variable. | ✅ | | | | ||
| [no-unnecessary-await](docs/rules/no-unnecessary-await.md) | Disallow awaiting non-promise values. | ✅ | 🔧 | | | ||
| [no-unreadable-array-destructuring](docs/rules/no-unreadable-array-destructuring.md) | Disallow unreadable array destructuring. | ✅ | 🔧 | | | ||
| [no-unreadable-iife](docs/rules/no-unreadable-iife.md) | Disallow unreadable IIFEs. | ✅ | | | | ||
| [no-unsafe-regex](docs/rules/no-unsafe-regex.md) | Disallow unsafe regular expressions. | | | | | ||
| [no-unused-properties](docs/rules/no-unused-properties.md) | Disallow unused object properties. | | | | | ||
| [no-useless-fallback-in-spread](docs/rules/no-useless-fallback-in-spread.md) | Disallow useless fallback when spreading in object literals. | ✅ | 🔧 | | | ||
| [no-useless-length-check](docs/rules/no-useless-length-check.md) | Disallow useless array length check. | ✅ | 🔧 | | | ||
| [no-useless-promise-resolve-reject](docs/rules/no-useless-promise-resolve-reject.md) | Disallow returning/yielding `Promise.resolve/reject()` in async functions or promise callbacks | ✅ | 🔧 | | | ||
| [no-useless-spread](docs/rules/no-useless-spread.md) | Disallow unnecessary spread. | ✅ | 🔧 | | | ||
| [no-useless-switch-case](docs/rules/no-useless-switch-case.md) | Disallow useless case in switch statements. | ✅ | | 💡 | | ||
| [no-useless-undefined](docs/rules/no-useless-undefined.md) | Disallow useless `undefined`. | ✅ | 🔧 | | | ||
| [no-zero-fractions](docs/rules/no-zero-fractions.md) | Disallow number literals with zero fractions or dangling dots. | ✅ | 🔧 | | | ||
| [number-literal-case](docs/rules/number-literal-case.md) | Enforce proper case for numeric literals. | ✅ | 🔧 | | | ||
| [numeric-separators-style](docs/rules/numeric-separators-style.md) | Enforce the style of numeric separators by correctly grouping digits. | ✅ | 🔧 | | | ||
| [prefer-add-event-listener](docs/rules/prefer-add-event-listener.md) | Prefer `.addEventListener()` and `.removeEventListener()` over `on`-functions. | ✅ | 🔧 | | | ||
| [prefer-array-find](docs/rules/prefer-array-find.md) | Prefer `.find(…)` and `.findLast(…)` over the first or last element from `.filter(…)`. | ✅ | 🔧 | 💡 | | ||
| [prefer-array-flat](docs/rules/prefer-array-flat.md) | Prefer `Array#flat()` over legacy techniques to flatten arrays. | ✅ | 🔧 | | | ||
| [prefer-array-flat-map](docs/rules/prefer-array-flat-map.md) | Prefer `.flatMap(…)` over `.map(…).flat()`. | ✅ | 🔧 | | | ||
| [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-at](docs/rules/prefer-at.md) | Prefer `.at()` method for index access and `String#charAt()`. | | 🔧 | 💡 | | ||
| [prefer-code-point](docs/rules/prefer-code-point.md) | Prefer `String#codePointAt(…)` over `String#charCodeAt(…)` and `String.fromCodePoint(…)` over `String.fromCharCode(…)`. | ✅ | | 💡 | | ||
| [prefer-date-now](docs/rules/prefer-date-now.md) | Prefer `Date.now()` to get the number of milliseconds since the Unix Epoch. | ✅ | 🔧 | | | ||
| [prefer-default-parameters](docs/rules/prefer-default-parameters.md) | Prefer default parameters over reassignment. | ✅ | 🔧 | 💡 | | ||
| [prefer-dom-node-append](docs/rules/prefer-dom-node-append.md) | Prefer `Node#append()` over `Node#appendChild()`. | ✅ | 🔧 | | | ||
| [prefer-dom-node-dataset](docs/rules/prefer-dom-node-dataset.md) | Prefer using `.dataset` on DOM elements over calling attribute methods. | ✅ | 🔧 | | | ||
| [prefer-dom-node-remove](docs/rules/prefer-dom-node-remove.md) | Prefer `childNode.remove()` over `parentNode.removeChild(childNode)`. | ✅ | 🔧 | 💡 | | ||
| [prefer-dom-node-text-content](docs/rules/prefer-dom-node-text-content.md) | Prefer `.textContent` over `.innerText`. | ✅ | | 💡 | | ||
| [prefer-event-target](docs/rules/prefer-event-target.md) | Prefer `EventTarget` over `EventEmitter`. | | | | | ||
| [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-json-parse-buffer](docs/rules/prefer-json-parse-buffer.md) | Prefer reading a JSON file as a buffer. | | 🔧 | | | ||
| [prefer-keyboard-event-key](docs/rules/prefer-keyboard-event-key.md) | Prefer `KeyboardEvent#key` over `KeyboardEvent#keyCode`. | ✅ | 🔧 | | | ||
| [prefer-logical-operator-over-ternary](docs/rules/prefer-logical-operator-over-ternary.md) | Prefer using a logical operator over a ternary. | ✅ | | 💡 | | ||
| [prefer-math-trunc](docs/rules/prefer-math-trunc.md) | Enforce the use of `Math.trunc` instead of bitwise operators. | ✅ | 🔧 | 💡 | | ||
| [prefer-modern-dom-apis](docs/rules/prefer-modern-dom-apis.md) | Prefer `.before()` over `.insertBefore()`, `.replaceWith()` over `.replaceChild()`, prefer one of `.before()`, `.after()`, `.append()` or `.prepend()` over `insertAdjacentText()` and `insertAdjacentElement()`. | ✅ | 🔧 | | | ||
| [prefer-modern-math-apis](docs/rules/prefer-modern-math-apis.md) | Prefer modern `Math` APIs over legacy patterns. | ✅ | 🔧 | | | ||
| [prefer-module](docs/rules/prefer-module.md) | Prefer JavaScript modules (ESM) over CommonJS. | ✅ | 🔧 | 💡 | | ||
| [prefer-native-coercion-functions](docs/rules/prefer-native-coercion-functions.md) | Prefer using `String`, `Number`, `BigInt`, `Boolean`, and `Symbol` directly. | ✅ | 🔧 | | | ||
| [prefer-negative-index](docs/rules/prefer-negative-index.md) | Prefer negative index over `.length - index` for `{String,Array,TypedArray}#{slice,at}()` and `Array#splice()`. | ✅ | 🔧 | | | ||
| [prefer-node-protocol](docs/rules/prefer-node-protocol.md) | Prefer using the `node:` protocol when importing Node.js builtin modules. | ✅ | 🔧 | | | ||
| [prefer-number-properties](docs/rules/prefer-number-properties.md) | Prefer `Number` static properties over global ones. | ✅ | 🔧 | 💡 | | ||
| [prefer-object-from-entries](docs/rules/prefer-object-from-entries.md) | Prefer using `Object.fromEntries(…)` to transform a list of key-value pairs into an object. | ✅ | 🔧 | | | ||
| [prefer-optional-catch-binding](docs/rules/prefer-optional-catch-binding.md) | Prefer omitting the `catch` binding parameter. | ✅ | 🔧 | | | ||
| [prefer-prototype-methods](docs/rules/prefer-prototype-methods.md) | Prefer borrowing methods from the prototype instead of the instance. | ✅ | 🔧 | | | ||
| [prefer-query-selector](docs/rules/prefer-query-selector.md) | Prefer `.querySelector()` over `.getElementById()`, `.querySelectorAll()` over `.getElementsByClassName()` and `.getElementsByTagName()`. | ✅ | 🔧 | | | ||
| [prefer-reflect-apply](docs/rules/prefer-reflect-apply.md) | Prefer `Reflect.apply()` over `Function#apply()`. | ✅ | 🔧 | | | ||
| [prefer-regexp-test](docs/rules/prefer-regexp-test.md) | Prefer `RegExp#test()` over `String#match()` and `RegExp#exec()`. | ✅ | 🔧 | | | ||
| [prefer-set-has](docs/rules/prefer-set-has.md) | Prefer `Set#has()` over `Array#includes()` when checking for existence or non-existence. | ✅ | 🔧 | 💡 | | ||
| [prefer-spread](docs/rules/prefer-spread.md) | Prefer the spread operator over `Array.from(…)`, `Array#concat(…)`, `Array#slice()` and `String#split('')`. | ✅ | 🔧 | 💡 | | ||
| [prefer-string-replace-all](docs/rules/prefer-string-replace-all.md) | Prefer `String#replaceAll()` over regex searches with the global flag. | | 🔧 | | | ||
| [prefer-string-slice](docs/rules/prefer-string-slice.md) | Prefer `String#slice()` over `String#substr()` and `String#substring()`. | ✅ | 🔧 | | | ||
| [prefer-string-starts-ends-with](docs/rules/prefer-string-starts-ends-with.md) | Prefer `String#startsWith()` & `String#endsWith()` over `RegExp#test()`. | ✅ | 🔧 | 💡 | | ||
| [prefer-string-trim-start-end](docs/rules/prefer-string-trim-start-end.md) | Prefer `String#trimStart()` / `String#trimEnd()` over `String#trimLeft()` / `String#trimRight()`. | ✅ | 🔧 | | | ||
| [prefer-switch](docs/rules/prefer-switch.md) | Prefer `switch` over multiple `else-if`. | ✅ | 🔧 | | | ||
| [prefer-ternary](docs/rules/prefer-ternary.md) | Prefer ternary expressions over simple `if-else` statements. | ✅ | 🔧 | | | ||
| [prefer-top-level-await](docs/rules/prefer-top-level-await.md) | Prefer top-level await over top-level promises and async function calls. | ✅ | | 💡 | | ||
| [prefer-type-error](docs/rules/prefer-type-error.md) | Enforce throwing `TypeError` in type checking conditions. | ✅ | 🔧 | | | ||
| [prevent-abbreviations](docs/rules/prevent-abbreviations.md) | Prevent abbreviations. | ✅ | 🔧 | | | ||
| [relative-url-style](docs/rules/relative-url-style.md) | Enforce consistent relative URL style. | ✅ | 🔧 | 💡 | | ||
| [require-array-join-separator](docs/rules/require-array-join-separator.md) | Enforce using the separator argument with `Array#join()`. | ✅ | 🔧 | | | ||
| [require-number-to-fixed-digits-argument](docs/rules/require-number-to-fixed-digits-argument.md) | Enforce using the digits argument with `Number#toFixed()`. | ✅ | 🔧 | | | ||
| [require-post-message-target-origin](docs/rules/require-post-message-target-origin.md) | Enforce using the `targetOrigin` argument with `window.postMessage()`. | | | 💡 | | ||
| [string-content](docs/rules/string-content.md) | Enforce better string content. | | 🔧 | 💡 | | ||
| [switch-case-braces](docs/rules/switch-case-braces.md) | Enforce consistent brace style for `case` clauses. | ✅ | 🔧 | | | ||
| [template-indent](docs/rules/template-indent.md) | Fix whitespace-insensitive template indentation. | ✅ | 🔧 | | | ||
| [text-encoding-identifier-case](docs/rules/text-encoding-identifier-case.md) | Enforce consistent case for text encoding identifiers. | ✅ | 🔧 | 💡 | | ||
| [throw-new-error](docs/rules/throw-new-error.md) | Require `new` when throwing an error. | ✅ | 🔧 | | | ||
<!-- /RULES_TABLE --> | ||
| Name | Description | 💼 | 🚫 | 🔧 | 💡 | | ||
| :----------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :- | :- | :- | :- | | ||
| [better-regex](docs/rules/better-regex.md) | Improve regexes by making them shorter, consistent, and safer. | ✅ | | 🔧 | | | ||
| [catch-error-name](docs/rules/catch-error-name.md) | Enforce a specific parameter name in catch clauses. | ✅ | | 🔧 | | | ||
| [consistent-destructuring](docs/rules/consistent-destructuring.md) | Use destructured variables over properties. | ✅ | | 🔧 | 💡 | | ||
| [consistent-function-scoping](docs/rules/consistent-function-scoping.md) | Move function definitions to the highest possible scope. | ✅ | | | | | ||
| [custom-error-definition](docs/rules/custom-error-definition.md) | Enforce correct `Error` subclassing. | | ✅ | 🔧 | | | ||
| [empty-brace-spaces](docs/rules/empty-brace-spaces.md) | Enforce no spaces between braces. | ✅ | | 🔧 | | | ||
| [error-message](docs/rules/error-message.md) | Enforce passing a `message` value when creating a built-in error. | ✅ | | | | | ||
| [escape-case](docs/rules/escape-case.md) | Require escape sequences to use uppercase values. | ✅ | | 🔧 | | | ||
| [expiring-todo-comments](docs/rules/expiring-todo-comments.md) | Add expiration conditions to TODO comments. | ✅ | | | | | ||
| [explicit-length-check](docs/rules/explicit-length-check.md) | Enforce explicitly comparing the `length` or `size` property of a value. | ✅ | | 🔧 | 💡 | | ||
| [filename-case](docs/rules/filename-case.md) | Enforce a case style for filenames. | ✅ | | | | | ||
| [import-style](docs/rules/import-style.md) | Enforce specific import styles per module. | ✅ | | | | | ||
| [new-for-builtins](docs/rules/new-for-builtins.md) | Enforce the use of `new` for all builtins, except `String`, `Number`, `Boolean`, `Symbol` and `BigInt`. | ✅ | | 🔧 | | | ||
| [no-abusive-eslint-disable](docs/rules/no-abusive-eslint-disable.md) | Enforce specifying rules to disable in `eslint-disable` comments. | ✅ | | | | | ||
| [no-array-callback-reference](docs/rules/no-array-callback-reference.md) | Prevent passing a function reference directly to iterator methods. | ✅ | | | 💡 | | ||
| [no-array-for-each](docs/rules/no-array-for-each.md) | Prefer `for…of` over the `forEach` method. | ✅ | | 🔧 | 💡 | | ||
| [no-array-method-this-argument](docs/rules/no-array-method-this-argument.md) | Disallow using the `this` argument in array methods. | ✅ | | 🔧 | 💡 | | ||
| [no-array-push-push](docs/rules/no-array-push-push.md) | Enforce combining multiple `Array#push()` into one call. | ✅ | | 🔧 | 💡 | | ||
| [no-array-reduce](docs/rules/no-array-reduce.md) | Disallow `Array#reduce()` and `Array#reduceRight()`. | ✅ | | | | | ||
| [no-await-expression-member](docs/rules/no-await-expression-member.md) | Disallow member access from await expression. | ✅ | | 🔧 | | | ||
| [no-console-spaces](docs/rules/no-console-spaces.md) | Do not use leading/trailing space between `console.log` parameters. | ✅ | | 🔧 | | | ||
| [no-document-cookie](docs/rules/no-document-cookie.md) | Do not use `document.cookie` directly. | ✅ | | | | | ||
| [no-empty-file](docs/rules/no-empty-file.md) | Disallow empty files. | ✅ | | | | | ||
| [no-for-loop](docs/rules/no-for-loop.md) | Do not use a `for` loop that can be replaced with a `for-of` loop. | ✅ | | 🔧 | | | ||
| [no-hex-escape](docs/rules/no-hex-escape.md) | Enforce the use of Unicode escapes instead of hexadecimal escapes. | ✅ | | 🔧 | | | ||
| [no-instanceof-array](docs/rules/no-instanceof-array.md) | Require `Array.isArray()` instead of `instanceof Array`. | ✅ | | 🔧 | | | ||
| [no-invalid-remove-event-listener](docs/rules/no-invalid-remove-event-listener.md) | Prevent calling `EventTarget#removeEventListener()` with the result of an expression. | ✅ | | | | | ||
| [no-keyword-prefix](docs/rules/no-keyword-prefix.md) | Disallow identifiers starting with `new` or `class`. | | ✅ | | | | ||
| [no-lonely-if](docs/rules/no-lonely-if.md) | Disallow `if` statements as the only statement in `if` blocks without `else`. | ✅ | | 🔧 | | | ||
| [no-negated-condition](docs/rules/no-negated-condition.md) | Disallow negated conditions. | ✅ | | 🔧 | | | ||
| [no-nested-ternary](docs/rules/no-nested-ternary.md) | Disallow nested ternary expressions. | ✅ | | 🔧 | | | ||
| [no-new-array](docs/rules/no-new-array.md) | Disallow `new Array()`. | ✅ | | 🔧 | 💡 | | ||
| [no-new-buffer](docs/rules/no-new-buffer.md) | Enforce the use of `Buffer.from()` and `Buffer.alloc()` instead of the deprecated `new Buffer()`. | ✅ | | 🔧 | 💡 | | ||
| [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()`. | ✅ | | | | | ||
| [no-static-only-class](docs/rules/no-static-only-class.md) | Disallow classes that only have static members. | ✅ | | 🔧 | | | ||
| [no-thenable](docs/rules/no-thenable.md) | Disallow `then` property. | ✅ | | | | | ||
| [no-this-assignment](docs/rules/no-this-assignment.md) | Disallow assigning `this` to a variable. | ✅ | | | | | ||
| [no-typeof-undefined](docs/rules/no-typeof-undefined.md) | Disallow comparing `undefined` using `typeof`. | ✅ | | 🔧 | 💡 | | ||
| [no-unnecessary-await](docs/rules/no-unnecessary-await.md) | Disallow awaiting non-promise values. | ✅ | | 🔧 | | | ||
| [no-unreadable-array-destructuring](docs/rules/no-unreadable-array-destructuring.md) | Disallow unreadable array destructuring. | ✅ | | 🔧 | | | ||
| [no-unreadable-iife](docs/rules/no-unreadable-iife.md) | Disallow unreadable IIFEs. | ✅ | | | | | ||
| [no-unsafe-regex](docs/rules/no-unsafe-regex.md) | Disallow unsafe regular expressions. | | ✅ | | | | ||
| [no-unused-properties](docs/rules/no-unused-properties.md) | Disallow unused object properties. | | ✅ | | | | ||
| [no-useless-fallback-in-spread](docs/rules/no-useless-fallback-in-spread.md) | Disallow useless fallback when spreading in object literals. | ✅ | | 🔧 | | | ||
| [no-useless-length-check](docs/rules/no-useless-length-check.md) | Disallow useless array length check. | ✅ | | 🔧 | | | ||
| [no-useless-promise-resolve-reject](docs/rules/no-useless-promise-resolve-reject.md) | Disallow returning/yielding `Promise.resolve/reject()` in async functions or promise callbacks | ✅ | | 🔧 | | | ||
| [no-useless-spread](docs/rules/no-useless-spread.md) | Disallow unnecessary spread. | ✅ | | 🔧 | | | ||
| [no-useless-switch-case](docs/rules/no-useless-switch-case.md) | Disallow useless case in switch statements. | ✅ | | | 💡 | | ||
| [no-useless-undefined](docs/rules/no-useless-undefined.md) | Disallow useless `undefined`. | ✅ | | 🔧 | | | ||
| [no-zero-fractions](docs/rules/no-zero-fractions.md) | Disallow number literals with zero fractions or dangling dots. | ✅ | | 🔧 | | | ||
| [number-literal-case](docs/rules/number-literal-case.md) | Enforce proper case for numeric literals. | ✅ | | 🔧 | | | ||
| [numeric-separators-style](docs/rules/numeric-separators-style.md) | Enforce the style of numeric separators by correctly grouping digits. | ✅ | | 🔧 | | | ||
| [prefer-add-event-listener](docs/rules/prefer-add-event-listener.md) | Prefer `.addEventListener()` and `.removeEventListener()` over `on`-functions. | ✅ | | 🔧 | | | ||
| [prefer-array-find](docs/rules/prefer-array-find.md) | Prefer `.find(…)` and `.findLast(…)` over the first or last element from `.filter(…)`. | ✅ | | 🔧 | 💡 | | ||
| [prefer-array-flat](docs/rules/prefer-array-flat.md) | Prefer `Array#flat()` over legacy techniques to flatten arrays. | ✅ | | 🔧 | | | ||
| [prefer-array-flat-map](docs/rules/prefer-array-flat-map.md) | Prefer `.flatMap(…)` over `.map(…).flat()`. | ✅ | | 🔧 | | | ||
| [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-at](docs/rules/prefer-at.md) | Prefer `.at()` method for index access and `String#charAt()`. | | ✅ | 🔧 | 💡 | | ||
| [prefer-code-point](docs/rules/prefer-code-point.md) | Prefer `String#codePointAt(…)` over `String#charCodeAt(…)` and `String.fromCodePoint(…)` over `String.fromCharCode(…)`. | ✅ | | | 💡 | | ||
| [prefer-date-now](docs/rules/prefer-date-now.md) | Prefer `Date.now()` to get the number of milliseconds since the Unix Epoch. | ✅ | | 🔧 | | | ||
| [prefer-default-parameters](docs/rules/prefer-default-parameters.md) | Prefer default parameters over reassignment. | ✅ | | 🔧 | 💡 | | ||
| [prefer-dom-node-append](docs/rules/prefer-dom-node-append.md) | Prefer `Node#append()` over `Node#appendChild()`. | ✅ | | 🔧 | | | ||
| [prefer-dom-node-dataset](docs/rules/prefer-dom-node-dataset.md) | Prefer using `.dataset` on DOM elements over calling attribute methods. | ✅ | | 🔧 | | | ||
| [prefer-dom-node-remove](docs/rules/prefer-dom-node-remove.md) | Prefer `childNode.remove()` over `parentNode.removeChild(childNode)`. | ✅ | | 🔧 | 💡 | | ||
| [prefer-dom-node-text-content](docs/rules/prefer-dom-node-text-content.md) | Prefer `.textContent` over `.innerText`. | ✅ | | | 💡 | | ||
| [prefer-event-target](docs/rules/prefer-event-target.md) | Prefer `EventTarget` over `EventEmitter`. | | ✅ | | | | ||
| [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-json-parse-buffer](docs/rules/prefer-json-parse-buffer.md) | Prefer reading a JSON file as a buffer. | | ✅ | 🔧 | | | ||
| [prefer-keyboard-event-key](docs/rules/prefer-keyboard-event-key.md) | Prefer `KeyboardEvent#key` over `KeyboardEvent#keyCode`. | ✅ | | 🔧 | | | ||
| [prefer-logical-operator-over-ternary](docs/rules/prefer-logical-operator-over-ternary.md) | Prefer using a logical operator over a ternary. | ✅ | | | 💡 | | ||
| [prefer-math-trunc](docs/rules/prefer-math-trunc.md) | Enforce the use of `Math.trunc` instead of bitwise operators. | ✅ | | 🔧 | 💡 | | ||
| [prefer-modern-dom-apis](docs/rules/prefer-modern-dom-apis.md) | Prefer `.before()` over `.insertBefore()`, `.replaceWith()` over `.replaceChild()`, prefer one of `.before()`, `.after()`, `.append()` or `.prepend()` over `insertAdjacentText()` and `insertAdjacentElement()`. | ✅ | | 🔧 | | | ||
| [prefer-modern-math-apis](docs/rules/prefer-modern-math-apis.md) | Prefer modern `Math` APIs over legacy patterns. | ✅ | | 🔧 | | | ||
| [prefer-module](docs/rules/prefer-module.md) | Prefer JavaScript modules (ESM) over CommonJS. | ✅ | | 🔧 | 💡 | | ||
| [prefer-native-coercion-functions](docs/rules/prefer-native-coercion-functions.md) | Prefer using `String`, `Number`, `BigInt`, `Boolean`, and `Symbol` directly. | ✅ | | 🔧 | | | ||
| [prefer-negative-index](docs/rules/prefer-negative-index.md) | Prefer negative index over `.length - index` for `{String,Array,TypedArray}#{slice,at}()` and `Array#splice()`. | ✅ | | 🔧 | | | ||
| [prefer-node-protocol](docs/rules/prefer-node-protocol.md) | Prefer using the `node:` protocol when importing Node.js builtin modules. | ✅ | | 🔧 | | | ||
| [prefer-number-properties](docs/rules/prefer-number-properties.md) | Prefer `Number` static properties over global ones. | ✅ | | 🔧 | 💡 | | ||
| [prefer-object-from-entries](docs/rules/prefer-object-from-entries.md) | Prefer using `Object.fromEntries(…)` to transform a list of key-value pairs into an object. | ✅ | | 🔧 | | | ||
| [prefer-optional-catch-binding](docs/rules/prefer-optional-catch-binding.md) | Prefer omitting the `catch` binding parameter. | ✅ | | 🔧 | | | ||
| [prefer-prototype-methods](docs/rules/prefer-prototype-methods.md) | Prefer borrowing methods from the prototype instead of the instance. | ✅ | | 🔧 | | | ||
| [prefer-query-selector](docs/rules/prefer-query-selector.md) | Prefer `.querySelector()` over `.getElementById()`, `.querySelectorAll()` over `.getElementsByClassName()` and `.getElementsByTagName()`. | ✅ | | 🔧 | | | ||
| [prefer-reflect-apply](docs/rules/prefer-reflect-apply.md) | Prefer `Reflect.apply()` over `Function#apply()`. | ✅ | | 🔧 | | | ||
| [prefer-regexp-test](docs/rules/prefer-regexp-test.md) | Prefer `RegExp#test()` over `String#match()` and `RegExp#exec()`. | ✅ | | 🔧 | 💡 | | ||
| [prefer-set-has](docs/rules/prefer-set-has.md) | Prefer `Set#has()` over `Array#includes()` when checking for existence or non-existence. | ✅ | | 🔧 | 💡 | | ||
| [prefer-set-size](docs/rules/prefer-set-size.md) | Prefer using `Set#size` instead of `Array#length`. | ✅ | | 🔧 | | | ||
| [prefer-spread](docs/rules/prefer-spread.md) | Prefer the spread operator over `Array.from(…)`, `Array#concat(…)`, `Array#slice()` and `String#split('')`. | ✅ | | 🔧 | 💡 | | ||
| [prefer-string-replace-all](docs/rules/prefer-string-replace-all.md) | Prefer `String#replaceAll()` over regex searches with the global flag. | | ✅ | 🔧 | | | ||
| [prefer-string-slice](docs/rules/prefer-string-slice.md) | Prefer `String#slice()` over `String#substr()` and `String#substring()`. | ✅ | | 🔧 | | | ||
| [prefer-string-starts-ends-with](docs/rules/prefer-string-starts-ends-with.md) | Prefer `String#startsWith()` & `String#endsWith()` over `RegExp#test()`. | ✅ | | 🔧 | 💡 | | ||
| [prefer-string-trim-start-end](docs/rules/prefer-string-trim-start-end.md) | Prefer `String#trimStart()` / `String#trimEnd()` over `String#trimLeft()` / `String#trimRight()`. | ✅ | | 🔧 | | | ||
| [prefer-switch](docs/rules/prefer-switch.md) | Prefer `switch` over multiple `else-if`. | ✅ | | 🔧 | | | ||
| [prefer-ternary](docs/rules/prefer-ternary.md) | Prefer ternary expressions over simple `if-else` statements. | ✅ | | 🔧 | | | ||
| [prefer-top-level-await](docs/rules/prefer-top-level-await.md) | Prefer top-level await over top-level promises and async function calls. | ✅ | | | 💡 | | ||
| [prefer-type-error](docs/rules/prefer-type-error.md) | Enforce throwing `TypeError` in type checking conditions. | ✅ | | 🔧 | | | ||
| [prevent-abbreviations](docs/rules/prevent-abbreviations.md) | Prevent abbreviations. | ✅ | | 🔧 | | | ||
| [relative-url-style](docs/rules/relative-url-style.md) | Enforce consistent relative URL style. | ✅ | | 🔧 | 💡 | | ||
| [require-array-join-separator](docs/rules/require-array-join-separator.md) | Enforce using the separator argument with `Array#join()`. | ✅ | | 🔧 | | | ||
| [require-number-to-fixed-digits-argument](docs/rules/require-number-to-fixed-digits-argument.md) | Enforce using the digits argument with `Number#toFixed()`. | ✅ | | 🔧 | | | ||
| [require-post-message-target-origin](docs/rules/require-post-message-target-origin.md) | Enforce using the `targetOrigin` argument with `window.postMessage()`. | | ✅ | | 💡 | | ||
| [string-content](docs/rules/string-content.md) | Enforce better string content. | | ✅ | 🔧 | 💡 | | ||
| [switch-case-braces](docs/rules/switch-case-braces.md) | Enforce consistent brace style for `case` clauses. | ✅ | | 🔧 | | | ||
| [template-indent](docs/rules/template-indent.md) | Fix whitespace-insensitive template indentation. | ✅ | | 🔧 | | | ||
| [text-encoding-identifier-case](docs/rules/text-encoding-identifier-case.md) | Enforce consistent case for text encoding identifiers. | ✅ | | 🔧 | 💡 | | ||
| [throw-new-error](docs/rules/throw-new-error.md) | Require `new` when throwing an error. | ✅ | | 🔧 | | | ||
<!-- end auto-generated rules list --> | ||
### Deprecated Rules | ||
@@ -166,0 +171,0 @@ |
@@ -24,2 +24,3 @@ 'use strict'; | ||
isUndefined: require('./is-undefined.js'), | ||
isNewExpression: require('./is-new-expression.js'), | ||
}; |
'use strict'; | ||
const cleanRegexp = require('clean-regexp'); | ||
const {optimize} = require('regexp-tree'); | ||
const quoteString = require('./utils/quote-string.js'); | ||
const escapeString = require('./utils/escape-string.js'); | ||
const {newExpressionSelector} = require('./selectors/index.js'); | ||
@@ -105,3 +105,3 @@ const {isStringLiteral} = require('./ast/index.js'); | ||
patternNode, | ||
quoteString(newPattern, patternNode.raw.charAt(0)), | ||
escapeString(newPattern, patternNode.raw.charAt(0)), | ||
), | ||
@@ -108,0 +108,0 @@ }; |
@@ -314,39 +314,2 @@ 'use strict'; | ||
// TODO[@fisker]: Improve `./utils/is-left-hand-side.js` with similar logic | ||
function isAssignmentLeftHandSide(node) { | ||
const {parent} = node; | ||
switch (parent.type) { | ||
case 'AssignmentExpression': | ||
case 'ForInStatement': | ||
case 'ForOfStatement': { | ||
return parent.left === node; | ||
} | ||
case 'UpdateExpression': { | ||
return parent.argument === node; | ||
} | ||
case 'Property': { | ||
return parent.value === node && isAssignmentLeftHandSide(parent); | ||
} | ||
case 'AssignmentPattern': { | ||
return parent.left === node && isAssignmentLeftHandSide(parent); | ||
} | ||
case 'ArrayPattern': { | ||
return parent.elements.includes(node) && isAssignmentLeftHandSide(parent); | ||
} | ||
case 'ObjectPattern': { | ||
return parent.properties.includes(node) && isAssignmentLeftHandSide(parent); | ||
} | ||
default: { | ||
return false; | ||
} | ||
} | ||
} | ||
function isFunctionParameterVariableReassigned(callbackFunction, context) { | ||
@@ -356,3 +319,3 @@ return context.getDeclaredVariables(callbackFunction) | ||
.some(variable => | ||
variable.references.some(reference => isAssignmentLeftHandSide(reference.identifier)), | ||
variable.references.some(reference => !reference.init && reference.isWrite()), | ||
); | ||
@@ -393,2 +356,4 @@ } | ||
|| (parameters.length === 1 && parameters[0].type === 'AssignmentPattern') | ||
// https://github.com/sindresorhus/eslint-plugin-unicorn/issues/1814 | ||
|| (parameters.length === 2 && parameters[1].type !== 'Identifier') | ||
|| parameters.some(({type, typeAnnotation}) => type === 'RestElement' || typeAnnotation) | ||
@@ -395,0 +360,0 @@ || !isFunctionParametersSafeToFix(callback, {scope, callExpression, allIdentifiers, context}) |
@@ -52,3 +52,3 @@ 'use strict'; | ||
|| isReadonly | ||
|| typeof accessibility !== 'undefined' | ||
|| accessibility !== undefined | ||
|| (Array.isArray(decorators) && decorators.length > 0) | ||
@@ -55,0 +55,0 @@ // TODO: Remove this when we drop support for `@typescript-eslint/parser` v4 |
'use strict'; | ||
const safeRegex = require('safe-regex'); | ||
const {newExpressionSelector} = require('./selectors/index.js'); | ||
const {isNewExpression} = require('./ast/index.js'); | ||
@@ -19,6 +20,3 @@ const MESSAGE_ID = 'no-unsafe-regex'; | ||
// Handle regex literal inside RegExp constructor in the other handler | ||
if ( | ||
node.parent.type === 'NewExpression' | ||
&& node.parent.callee.name === 'RegExp' | ||
) { | ||
if (isNewExpression(node.parent, {name: 'RegExp'})) { | ||
return; | ||
@@ -25,0 +23,0 @@ } |
@@ -9,3 +9,11 @@ 'use strict'; | ||
const typedArray = require('./shared/typed-array.js'); | ||
const {removeParentheses, fixSpaceAroundKeyword} = require('./fix/index.js'); | ||
const { | ||
removeParentheses, | ||
fixSpaceAroundKeyword, | ||
addParenthesizesToReturnOrThrowExpression, | ||
} = require('./fix/index.js'); | ||
const isOnSameLine = require('./utils/is-on-same-line.js'); | ||
const { | ||
isParenthesized, | ||
} = require('./utils/parentheses.js'); | ||
@@ -16,2 +24,3 @@ const SPREAD_IN_LIST = 'spread-in-list'; | ||
const ITERABLE_TO_ARRAY_IN_YIELD_STAR = 'iterable-to-array-in-yield-star'; | ||
const CLONE_ARRAY = 'clone-array'; | ||
const messages = { | ||
@@ -22,2 +31,3 @@ [SPREAD_IN_LIST]: 'Spread an {{argumentType}} literal in {{parentDescription}} is unnecessary.', | ||
[ITERABLE_TO_ARRAY_IN_YIELD_STAR]: '`yield*` can delegate iterable, it\'s unnecessary to convert to an array.', | ||
[CLONE_ARRAY]: 'Unnecessarily cloning an array.', | ||
}; | ||
@@ -32,3 +42,3 @@ | ||
const iterableToArraySelector = [ | ||
const singleArraySpreadSelector = [ | ||
'ArrayExpression', | ||
@@ -56,8 +66,43 @@ '[elements.length=1]', | ||
' > ', | ||
`${iterableToArraySelector}.arguments:first-child`, | ||
`${singleArraySpreadSelector}.arguments:first-child`, | ||
].join(''), | ||
`ForOfStatement > ${iterableToArraySelector}.right`, | ||
`YieldExpression[delegate=true] > ${iterableToArraySelector}.argument`, | ||
`ForOfStatement > ${singleArraySpreadSelector}.right`, | ||
`YieldExpression[delegate=true] > ${singleArraySpreadSelector}.argument`, | ||
]); | ||
const uselessArrayCloneSelector = [ | ||
`${singleArraySpreadSelector} > .elements:first-child > .argument`, | ||
matches([ | ||
// Array methods returns a new array | ||
methodCallSelector([ | ||
'concat', | ||
'copyWithin', | ||
'filter', | ||
'flat', | ||
'flatMap', | ||
'map', | ||
'slice', | ||
'splice', | ||
]), | ||
// `String#split()` | ||
methodCallSelector('split'), | ||
// `Object.keys()` and `Object.values()` | ||
methodCallSelector({object: 'Object', methods: ['keys', 'values'], argumentsLength: 1}), | ||
// `await Promise.all()` and `await Promise.allSettled` | ||
[ | ||
'AwaitExpression', | ||
methodCallSelector({ | ||
object: 'Promise', | ||
methods: ['all', 'allSettled'], | ||
argumentsLength: 1, | ||
path: 'argument', | ||
}), | ||
].join(''), | ||
// `Array.from()`, `Array.of()` | ||
methodCallSelector({object: 'Array', methods: ['from', 'of']}), | ||
// `new Array()` | ||
newExpressionSelector('Array'), | ||
]), | ||
].join(''); | ||
const parentDescriptions = { | ||
@@ -89,2 +134,55 @@ ArrayExpression: 'array literal', | ||
function * unwrapSingleArraySpread(fixer, arrayExpression, sourceCode) { | ||
const [ | ||
openingBracketToken, | ||
spreadToken, | ||
thirdToken, | ||
] = sourceCode.getFirstTokens(arrayExpression, 3); | ||
// `[...value]` | ||
// ^ | ||
yield fixer.remove(openingBracketToken); | ||
// `[...value]` | ||
// ^^^ | ||
yield fixer.remove(spreadToken); | ||
const [ | ||
commaToken, | ||
closingBracketToken, | ||
] = sourceCode.getLastTokens(arrayExpression, 2); | ||
// `[...value]` | ||
// ^ | ||
yield fixer.remove(closingBracketToken); | ||
// `[...value,]` | ||
// ^ | ||
if (isCommaToken(commaToken)) { | ||
yield fixer.remove(commaToken); | ||
} | ||
/* | ||
```js | ||
function foo() { | ||
return [ | ||
...value, | ||
]; | ||
} | ||
``` | ||
*/ | ||
const {parent} = arrayExpression; | ||
if ( | ||
(parent.type === 'ReturnStatement' || parent.type === 'ThrowStatement') | ||
&& parent.argument === arrayExpression | ||
&& !isOnSameLine(openingBracketToken, thirdToken) | ||
&& !isParenthesized(arrayExpression, sourceCode) | ||
) { | ||
yield * addParenthesizesToReturnOrThrowExpression(fixer, parent, sourceCode); | ||
return; | ||
} | ||
yield * fixSpaceAroundKeyword(fixer, arrayExpression, sourceCode); | ||
} | ||
/** @param {import('eslint').Rule.RuleContext} context */ | ||
@@ -147,4 +245,4 @@ const create = context => { | ||
// `call([foo, , bar])` | ||
// ^ Replace holes with `undefined` | ||
// `call(...[foo, , bar])` | ||
// ^ Replace holes with `undefined` | ||
yield fixer.insertTextBefore(commaToken, 'undefined'); | ||
@@ -155,4 +253,4 @@ } | ||
}, | ||
[uselessIterableToArraySelector](array) { | ||
const {parent} = array; | ||
[uselessIterableToArraySelector](arrayExpression) { | ||
const {parent} = arrayExpression; | ||
let parentDescription = ''; | ||
@@ -184,40 +282,16 @@ let messageId = ITERABLE_TO_ARRAY; | ||
return { | ||
node: array, | ||
node: arrayExpression, | ||
messageId, | ||
data: {parentDescription}, | ||
* fix(fixer) { | ||
if (parent.type === 'ForOfStatement') { | ||
yield * fixSpaceAroundKeyword(fixer, array, sourceCode); | ||
} | ||
const [ | ||
openingBracketToken, | ||
spreadToken, | ||
] = sourceCode.getFirstTokens(array, 2); | ||
// `[...iterable]` | ||
// ^ | ||
yield fixer.remove(openingBracketToken); | ||
// `[...iterable]` | ||
// ^^^ | ||
yield fixer.remove(spreadToken); | ||
const [ | ||
commaToken, | ||
closingBracketToken, | ||
] = sourceCode.getLastTokens(array, 2); | ||
// `[...iterable]` | ||
// ^ | ||
yield fixer.remove(closingBracketToken); | ||
// `[...iterable,]` | ||
// ^ | ||
if (isCommaToken(commaToken)) { | ||
yield fixer.remove(commaToken); | ||
} | ||
}, | ||
fix: fixer => unwrapSingleArraySpread(fixer, arrayExpression, sourceCode), | ||
}; | ||
}, | ||
[uselessArrayCloneSelector](node) { | ||
const arrayExpression = node.parent.parent; | ||
return { | ||
node: arrayExpression, | ||
messageId: CLONE_ARRAY, | ||
fix: fixer => unwrapSingleArraySpread(fixer, arrayExpression, sourceCode), | ||
}; | ||
}, | ||
}; | ||
@@ -224,0 +298,0 @@ }; |
@@ -72,14 +72,22 @@ 'use strict'; | ||
return compareFunctionNames.has(name) | ||
// https://vuejs.org/api/reactivity-core.html#ref | ||
|| name === 'ref' | ||
// `array.push(undefined)` | ||
|| name === 'push' | ||
// `array.unshift(undefined)` | ||
|| name === 'unshift' | ||
// `array.includes(undefined)` | ||
|| name === 'includes' | ||
// `set.add(undefined)` | ||
|| name === 'add' | ||
// `set.has(undefined)` | ||
|| name === 'has' | ||
// `map.set(foo, undefined)` | ||
|| name === 'set' | ||
// `array.push(undefined)` | ||
|| name === 'push' | ||
// `array.unshift(undefined)` | ||
|| name === 'unshift' | ||
// `React.createContext(undefined)` | ||
|| name === 'createContext'; | ||
|| name === 'createContext' | ||
// https://vuejs.org/api/reactivity-core.html#ref | ||
|| name === 'ref'; | ||
}; | ||
@@ -86,0 +94,0 @@ |
@@ -97,3 +97,3 @@ 'use strict'; | ||
const {left: memberExpression, right: assignedExpression} = node; | ||
const {left: memberExpression, right: assignedExpression, operator} = node; | ||
@@ -136,3 +136,7 @@ if ( | ||
extra = extraMessages.error; | ||
} else { | ||
} else if ( | ||
operator === '=' | ||
&& node.parent.type === 'ExpressionStatement' | ||
&& node.parent.expression === node | ||
) { | ||
fix = fixer => fixCode(fixer, context.getSourceCode(), node, memberExpression); | ||
@@ -139,0 +143,0 @@ } |
'use strict'; | ||
const isValidVariableName = require('./utils/is-valid-variable-name.js'); | ||
const quoteString = require('./utils/quote-string.js'); | ||
const {isIdentifierName} = require('@babel/helper-validator-identifier'); | ||
const escapeString = require('./utils/escape-string.js'); | ||
const {methodCallSelector, matches} = require('./selectors/index.js'); | ||
@@ -47,3 +47,3 @@ | ||
case 'removeAttribute': { | ||
text = isValidVariableName(name) ? `.${name}` : `[${quoteString(name, nameNode.raw.charAt(0))}]`; | ||
text = isIdentifierName(name) ? `.${name}` : `[${escapeString(name, nameNode.raw.charAt(0))}]`; | ||
text = `${datasetText}${text}`; | ||
@@ -64,3 +64,3 @@ if (method === 'setAttribute') { | ||
case 'hasAttribute': { | ||
text = `Object.hasOwn(${datasetText}, ${quoteString(name, nameNode.raw.charAt(0))})`; | ||
text = `Object.hasOwn(${datasetText}, ${escapeString(name, nameNode.raw.charAt(0))})`; | ||
break; | ||
@@ -67,0 +67,0 @@ } |
'use strict'; | ||
const quoteString = require('./utils/quote-string.js'); | ||
const escapeString = require('./utils/escape-string.js'); | ||
const translateToKey = require('./shared/event-keys.js'); | ||
@@ -100,3 +100,3 @@ const {isNumberLiteral} = require('./ast/index.js'); | ||
fixer.replaceText(node, 'key'), | ||
fixer.replaceText(right, quoteString(key)), | ||
fixer.replaceText(right, escapeString(key)), | ||
]; | ||
@@ -103,0 +103,0 @@ }; |
@@ -5,3 +5,3 @@ 'use strict'; | ||
const {methodCallSelector} = require('./selectors/index.js'); | ||
const {isRegexLiteral} = require('./ast/index.js'); | ||
const {isRegexLiteral, isNewExpression} = require('./ast/index.js'); | ||
const {isBooleanNode} = require('./utils/boolean.js'); | ||
@@ -12,5 +12,7 @@ const shouldAddParenthesesToMemberExpressionObject = require('./utils/should-add-parentheses-to-member-expression-object.js'); | ||
const STRING_MATCH = 'string-match'; | ||
const SUGGESTION = 'suggestion'; | ||
const messages = { | ||
[REGEXP_EXEC]: 'Prefer `.test(…)` over `.exec(…)`.', | ||
[STRING_MATCH]: 'Prefer `RegExp#test(…)` over `String#match(…)`.', | ||
[SUGGESTION]: 'Switch to `RegExp#test(…)`.', | ||
}; | ||
@@ -72,9 +74,18 @@ | ||
const isRegExpNode = node => | ||
isRegexLiteral(node) | ||
|| ( | ||
node.type === 'NewExpression' | ||
&& node.callee.type === 'Identifier' | ||
&& node.callee.name === 'RegExp' | ||
const isRegExpNode = node => isRegexLiteral(node) || isNewExpression(node, {name: 'RegExp'}); | ||
const isRegExpWithoutGlobalFlag = (node, scope) => { | ||
const staticResult = getStaticValue(node, scope); | ||
// Don't know if there is `g` flag | ||
if (!staticResult) { | ||
return false; | ||
} | ||
const {value} = staticResult; | ||
return ( | ||
Object.prototype.toString.call(value) === '[object RegExp]' | ||
&& !value.global | ||
); | ||
}; | ||
@@ -103,16 +114,18 @@ /** @param {import('eslint').Rule.RuleContext} context */ | ||
if (!isRegExpNode(regexpNode)) { | ||
const staticResult = getStaticValue(regexpNode, context.getScope()); | ||
if (staticResult) { | ||
const {value} = staticResult; | ||
if ( | ||
Object.prototype.toString.call(value) !== '[object RegExp]' | ||
|| value.flags.includes('g') | ||
) { | ||
return problem; | ||
} | ||
} | ||
const fixFunction = fixer => fix(fixer, nodes, context.getSourceCode()); | ||
if ( | ||
isRegExpNode(regexpNode) | ||
|| isRegExpWithoutGlobalFlag(regexpNode, context.getScope()) | ||
) { | ||
problem.fix = fixFunction; | ||
} else { | ||
problem.suggest = [ | ||
{ | ||
messageId: SUGGESTION, | ||
fix: fixFunction, | ||
}, | ||
]; | ||
} | ||
problem.fix = fixer => fix(fixer, nodes, context.getSourceCode()); | ||
return problem; | ||
@@ -132,4 +145,5 @@ }, | ||
fixable: 'code', | ||
hasSuggestions: true, | ||
messages, | ||
}, | ||
}; |
'use strict'; | ||
const quoteString = require('./utils/quote-string.js'); | ||
const {getStaticValue} = require('eslint-utils'); | ||
const {parse: parseRegExp} = require('regjsparser'); | ||
const escapeString = require('./utils/escape-string.js'); | ||
const {methodCallSelector} = require('./selectors/index.js'); | ||
const {isRegexLiteral} = require('./ast/index.js'); | ||
const {isRegexLiteral, isNewExpression} = require('./ast/index.js'); | ||
const MESSAGE_ID = 'prefer-string-replace-all'; | ||
const MESSAGE_ID_USE_REPLACE_ALL = 'method'; | ||
const MESSAGE_ID_USE_STRING = 'pattern'; | ||
const messages = { | ||
[MESSAGE_ID]: 'Prefer `String#replaceAll()` over `String#replace()`.', | ||
[MESSAGE_ID_USE_REPLACE_ALL]: 'Prefer `String#replaceAll()` over `String#replace()`.', | ||
[MESSAGE_ID_USE_STRING]: 'This pattern can be replaced with {{replacement}}.', | ||
}; | ||
const selector = methodCallSelector({ | ||
method: 'replace', | ||
methods: ['replace', 'replaceAll'], | ||
argumentsLength: 2, | ||
}); | ||
const isRegexWithGlobalFlag = node => | ||
isRegexLiteral(node) | ||
&& node.regex.flags.replace('u', '') === 'g'; | ||
function getPatternReplacement(node) { | ||
if (!isRegexLiteral(node)) { | ||
return; | ||
} | ||
function isLiteralCharactersOnly(node) { | ||
const searchPattern = node.regex.pattern; | ||
return !/[$()*+.?[\\\]^{}]/.test(searchPattern.replace(/\\[$()*+.?[\\\]^{}]/g, '')); | ||
} | ||
const {pattern, flags} = node.regex; | ||
if (flags.replace('u', '') !== 'g') { | ||
return; | ||
} | ||
function removeEscapeCharacters(regexString) { | ||
let fixedString = regexString; | ||
let index = 0; | ||
do { | ||
index = fixedString.indexOf('\\', index); | ||
const tree = parseRegExp(pattern, flags, { | ||
unicodePropertyEscape: true, | ||
namedGroups: true, | ||
lookbehind: true, | ||
}); | ||
if (index >= 0) { | ||
fixedString = fixedString.slice(0, index) + fixedString.slice(index + 1); | ||
index++; | ||
} | ||
} while (index >= 0); | ||
const parts = tree.type === 'alternative' ? tree.body : [tree]; | ||
if (parts.some(part => part.type !== 'value')) { | ||
return; | ||
} | ||
return fixedString; | ||
// TODO: Preserve escape | ||
const string = String.fromCodePoint(...parts.map(part => part.codePoint)); | ||
return escapeString(string); | ||
} | ||
const isRegExpWithGlobalFlag = (node, scope) => { | ||
if (isRegexLiteral(node)) { | ||
return node.regex.flags.includes('g'); | ||
} | ||
if ( | ||
isNewExpression(node, {name: 'RegExp'}) | ||
&& node.arguments[0]?.type !== 'SpreadElement' | ||
&& node.arguments[1]?.type === 'Literal' | ||
&& typeof node.arguments[1].value === 'string' | ||
) { | ||
return node.arguments[1].value.includes('g'); | ||
} | ||
const staticResult = getStaticValue(node, scope); | ||
// Don't know if there is `g` flag | ||
if (!staticResult) { | ||
return false; | ||
} | ||
const {value} = staticResult; | ||
return ( | ||
Object.prototype.toString.call(value) === '[object RegExp]' | ||
&& value.global | ||
); | ||
}; | ||
/** @param {import('eslint').Rule.RuleContext} context */ | ||
const create = () => ({ | ||
const create = context => ({ | ||
[selector](node) { | ||
const {arguments: arguments_, callee} = node; | ||
const [search] = arguments_; | ||
const { | ||
arguments: [pattern], | ||
callee: {property}, | ||
} = node; | ||
if (!isRegexWithGlobalFlag(search) || !isLiteralCharactersOnly(search)) { | ||
if (!isRegExpWithGlobalFlag(pattern, context.getScope())) { | ||
return; | ||
} | ||
const methodName = property.name; | ||
const patternReplacement = getPatternReplacement(pattern); | ||
if (methodName === 'replaceAll') { | ||
if (!patternReplacement) { | ||
return; | ||
} | ||
return { | ||
node: pattern, | ||
messageId: MESSAGE_ID_USE_STRING, | ||
data: { | ||
// Show `This pattern can be replaced with a string literal.` for long strings | ||
replacement: patternReplacement.length < 20 ? patternReplacement : 'a string literal', | ||
}, | ||
/** @param {import('eslint').Rule.RuleFixer} fixer */ | ||
fix: fixer => fixer.replaceText(pattern, patternReplacement), | ||
}; | ||
} | ||
return { | ||
node, | ||
messageId: MESSAGE_ID, | ||
fix: fixer => [ | ||
fixer.insertTextAfter(callee, 'All'), | ||
fixer.replaceText(search, quoteString(removeEscapeCharacters(search.regex.pattern))), | ||
], | ||
node: property, | ||
messageId: MESSAGE_ID_USE_REPLACE_ALL, | ||
/** @param {import('eslint').Rule.RuleFixer} fixer */ | ||
* fix(fixer) { | ||
yield fixer.insertTextAfter(property, 'All'); | ||
if (!patternReplacement) { | ||
return; | ||
} | ||
yield fixer.replaceText(pattern, patternReplacement); | ||
}, | ||
}; | ||
@@ -58,0 +121,0 @@ }, |
'use strict'; | ||
const {isParenthesized, getStaticValue} = require('eslint-utils'); | ||
const {methodCallSelector} = require('./selectors/index.js'); | ||
const quoteString = require('./utils/quote-string.js'); | ||
const escapeString = require('./utils/escape-string.js'); | ||
const shouldAddParenthesesToMemberExpressionObject = require('./utils/should-add-parentheses-to-member-expression-object.js'); | ||
@@ -160,3 +160,3 @@ const shouldAddParenthesesToLogicalExpressionChild = require('./utils/should-add-parentheses-to-logical-expression-child.js'); | ||
// Replace argument with result.string | ||
yield fixer.replaceTextRange(getParenthesizedRange(target, sourceCode), quoteString(result.string)); | ||
yield fixer.replaceTextRange(getParenthesizedRange(target, sourceCode), escapeString(result.string)); | ||
} | ||
@@ -163,0 +163,0 @@ |
'use strict'; | ||
const {findVariable, getFunctionHeadLocation} = require('eslint-utils'); | ||
const {matches, memberExpressionSelector} = require('./selectors/index.js'); | ||
const {matches, not, memberExpressionSelector} = require('./selectors/index.js'); | ||
@@ -18,3 +18,6 @@ const ERROR_PROMISE = 'promise'; | ||
const topLevelCallExpression = 'CallExpression:not(:function *)'; | ||
const topLevelCallExpression = [ | ||
'CallExpression', | ||
not([':function *', 'ClassDeclaration *', 'ClassExpression *']), | ||
].join(''); | ||
const iife = [ | ||
@@ -97,3 +100,4 @@ topLevelCallExpression, | ||
if ( | ||
!( | ||
!value | ||
|| !( | ||
( | ||
@@ -100,0 +104,0 @@ value.type === 'ArrowFunctionExpression' |
@@ -144,2 +144,12 @@ 'use strict'; | ||
// `retVal` -> `['returnValue', 'Value']` -> `['returnValue']` | ||
for (const parts of samples) { | ||
for (let index = parts.length - 1; index > 0; index--) { | ||
const word = parts[index]; | ||
if (/^[A-Za-z]+$/.test(word) && parts[index - 1].endsWith(parts[index])) { | ||
parts.splice(index, 1); | ||
} | ||
} | ||
} | ||
return { | ||
@@ -146,0 +156,0 @@ total, |
'use strict'; | ||
const quoteString = require('./utils/quote-string.js'); | ||
const escapeString = require('./utils/escape-string.js'); | ||
const escapeTemplateElementRaw = require('./utils/escape-template-element-raw.js'); | ||
@@ -111,3 +111,3 @@ const {replaceTemplateElement} = require('./fix/index.js'); | ||
node, | ||
quoteString(fixed, raw[0]), | ||
escapeString(fixed, raw[0]), | ||
) | ||
@@ -114,0 +114,0 @@ : fixer => replaceTemplateElement( |
'use strict'; | ||
const {getStaticValue} = require('eslint-utils'); | ||
// Copied from https://github.com/eslint/eslint/blob/c3e9accce2f61b04ab699fd37c90703305281aa3/lib/rules/utils/ast-utils.js#L379 | ||
// Copied from https://github.com/eslint/eslint/blob/94ba68d76a6940f68ff82eea7332c6505f93df76/lib/rules/utils/ast-utils.js#L392 | ||
@@ -131,3 +131,4 @@ /** | ||
case 'Identifier': { | ||
case 'Identifier': | ||
case 'PrivateIdentifier': { | ||
return left.name === right.name; | ||
@@ -147,7 +148,19 @@ } | ||
// X.y = x["y"] | ||
// `x.y = x["y"]` | ||
if (nameA !== undefined) { | ||
return ( | ||
isSameReference(left.object, right.object) | ||
&& nameA === getStaticPropertyName(right) | ||
); | ||
} | ||
/* | ||
`x[0] = x[0]` | ||
`x[y] = x[y]` | ||
`x.y = x.y` | ||
*/ | ||
return ( | ||
typeof nameA !== 'undefined' | ||
left.computed === right.computed | ||
&& isSameReference(left.object, right.object) | ||
&& nameA === getStaticPropertyName(right) | ||
&& isSameReference(left.property, right.property) | ||
); | ||
@@ -154,0 +167,0 @@ } |
@@ -37,3 +37,3 @@ 'use strict'; | ||
|| node.type === 'AssignmentExpression' | ||
|| node.type === 'AssignmentExpression' | ||
|| node.type === 'ArrowFunctionExpression' | ||
|| node.type === 'YieldExpression' | ||
@@ -40,0 +40,0 @@ || node.type === 'SequenceExpression' |
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
578471
209
18113
217
17
28
+ Addedjsesc@3.0.2
+ Addedregjsparser@0.9.1
+ Addedjsesc@0.5.03.0.2(transitive)
+ Addedregjsparser@0.9.1(transitive)
Updatedci-info@^3.6.1
Updatedsemver@^7.3.8