diff options
author | Antoine du Hamel <duhamelantoine1995@gmail.com> | 2021-01-06 21:19:36 +0300 |
---|---|---|
committer | Michaƫl Zasso <targos@protonmail.com> | 2021-09-02 00:24:52 +0300 |
commit | d7e2318e749013291aa92d94e2e2a3f694663d04 (patch) | |
tree | 8f9b497a9da7c4883ca9e84136df0a8a02d9a7e5 /tools | |
parent | 1ce81079df0536110892e073e6a854e71e23062e (diff) |
tools: add ESLint rule no-array-destructuring
Iterating over arrays should be avoided because it relies on
user-mutable global methods (`Array.prototype[Symbol.iterator]`
and `%ArrayIteratorPrototype%.next`), we should instead use
other alternatives. This commit adds a rule that disallow
array destructuring syntax in favor of object destructuring syntax.
Note that you can ignore this rule if you are using
the array destructuring syntax over a safe iterable, or
actually want to iterate over a user-provided object.
PR-URL: https://github.com/nodejs/node/pull/36818
Reviewed-By: Rich Trott <rtrott@gmail.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/eslint-rules/no-array-destructuring.js | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/tools/eslint-rules/no-array-destructuring.js b/tools/eslint-rules/no-array-destructuring.js new file mode 100644 index 00000000000..81667e698fb --- /dev/null +++ b/tools/eslint-rules/no-array-destructuring.js @@ -0,0 +1,83 @@ +/** + * @fileoverview Iterating over arrays should be avoided because it relies on + * user-mutable global methods (`Array.prototype[Symbol.iterator]` + * and `%ArrayIteratorPrototype%.next`), we should instead use + * other alternatives. This file defines a rule that disallow + * array destructuring syntax in favor of object destructuring + * syntax. Note that you can ignore this rule if you are using + * the array destructuring syntax over a safe iterable, or + * actually want to iterate over a user-provided object. + * @author aduh95 <duhamelantoine1995@gmail.com> + */ +'use strict'; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +const USE_OBJ_DESTRUCTURING = + 'Use object destructuring instead of array destructuring.'; +const USE_ARRAY_METHODS = + 'Use primordials.ArrayPrototypeSlice to avoid unsafe array iteration.'; + +const findComma = (sourceCode, elements, i, start) => { + if (i === 0) + return sourceCode.getTokenAfter(sourceCode.getTokenByRangeStart(start)); + + let element; + const originalIndex = i; + while (i && !element) { + element = elements[--i]; + } + let token = sourceCode.getTokenAfter( + element ?? sourceCode.getTokenByRangeStart(start) + ); + for (; i < originalIndex; i++) { + token = sourceCode.getTokenAfter(token); + } + return token; +}; +const createFix = (fixer, sourceCode, { range: [start, end], elements }) => [ + fixer.replaceTextRange([start, start + 1], '{'), + fixer.replaceTextRange([end - 1, end], '}'), + ...elements.map((node, i) => + (node === null ? + fixer.remove(findComma(sourceCode, elements, i, start)) : + fixer.insertTextBefore(node, i + ':')) + ), +]; +const arrayPatternContainsRestOperator = ({ elements }) => + elements?.find((node) => node?.type === 'RestElement'); + +module.exports = { + meta: { + type: 'suggestion', + fixable: 'code', + schema: [], + }, + create(context) { + const sourceCode = context.getSourceCode(); + + return { + ArrayPattern(node) { + const hasRest = arrayPatternContainsRestOperator(node); + context.report({ + message: hasRest ? USE_ARRAY_METHODS : USE_OBJ_DESTRUCTURING, + node: hasRest || node, + fix: hasRest ? + undefined : + (fixer) => [ + ...(node.parent.type === 'AssignmentExpression' ? + [ + fixer.insertTextBefore(node.parent, '('), + fixer.insertTextAfter(node.parent, ')'), + ] : + []), + ...createFix(fixer, sourceCode, node), + ], + }); + + }, + }; + }, +}; |