eslint-plugin-unicorn 63.0.0 → 65.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +26 -18
- package/package.json +32 -30
- package/readme.md +183 -147
- package/rules/ast/call-or-new-expression.js +3 -5
- package/rules/ast/literal.js +1 -6
- package/rules/better-dom-traversing.js +291 -0
- package/rules/catch-error-name.js +3 -3
- package/rules/consistent-compound-words.js +452 -0
- package/rules/consistent-destructuring.js +234 -22
- package/rules/consistent-function-scoping.js +35 -11
- package/rules/consistent-json-file-read.js +245 -0
- package/rules/consistent-template-literal-escape.js +52 -0
- package/rules/custom-error-definition.js +176 -71
- package/rules/dom-node-dataset.js +431 -0
- package/rules/escape-case.js +2 -1
- package/rules/expiring-todo-comments.js +56 -102
- package/rules/explicit-length-check.js +145 -33
- package/rules/filename-case.js +97 -13
- package/rules/fix/append-argument.js +1 -1
- package/rules/fix/remove-expression-statement.js +1 -0
- package/rules/import-style.js +30 -10
- package/rules/index.js +37 -3
- package/rules/isolated-functions.js +11 -5
- package/rules/no-accessor-recursion.js +1 -2
- package/rules/no-anonymous-default-export.js +9 -11
- package/rules/no-array-callback-reference.js +148 -22
- package/rules/no-array-fill-with-reference-type.js +127 -0
- package/rules/no-array-for-each.js +18 -3
- package/rules/no-array-from-fill.js +76 -0
- package/rules/no-array-method-this-argument.js +1 -1
- package/rules/no-array-reduce.js +509 -2
- package/rules/no-blob-to-file.js +299 -0
- package/rules/no-canvas-to-image.js +152 -0
- package/rules/no-confusing-array-splice.js +164 -0
- package/rules/no-duplicate-set-values.js +57 -0
- package/rules/no-empty-file.js +31 -2
- package/rules/no-exports-in-scripts.js +34 -0
- package/rules/no-for-loop.js +1 -5
- package/rules/no-hex-escape.js +1 -1
- package/rules/no-incorrect-query-selector.js +347 -0
- package/rules/no-instanceof-builtins.js +4 -6
- package/rules/no-invalid-fetch-options.js +1 -1
- package/rules/no-invalid-file-input-accept.js +475 -0
- package/rules/no-keyword-prefix.js +23 -5
- package/rules/no-late-current-target-access.js +166 -0
- package/rules/no-lonely-if.js +152 -52
- package/rules/no-manually-wrapped-comments.js +151 -0
- package/rules/no-null.js +16 -5
- package/rules/no-process-exit.js +1 -1
- package/rules/no-this-outside-of-class.js +75 -0
- package/rules/no-typeof-undefined.js +7 -4
- package/rules/no-unnecessary-nested-ternary.js +132 -0
- package/rules/no-unnecessary-polyfills.js +253 -24
- package/rules/no-unreadable-iife.js +33 -3
- package/rules/no-unused-array-method-return.js +301 -0
- package/rules/no-unused-properties.js +13 -19
- package/rules/no-useless-iterator-to-array.js +249 -0
- package/rules/no-useless-length-check.js +5 -11
- package/rules/no-useless-promise-resolve-reject.js +5 -5
- package/rules/no-useless-spread.js +53 -4
- package/rules/no-useless-undefined.js +62 -46
- package/rules/numeric-separators-style.js +17 -6
- package/rules/prefer-add-event-listener.js +1 -0
- package/rules/prefer-array-find.js +1 -0
- package/rules/prefer-array-flat.js +76 -8
- package/rules/prefer-array-last-methods.js +93 -0
- package/rules/prefer-array-some.js +74 -8
- package/rules/prefer-at.js +118 -57
- package/rules/prefer-class-fields.js +2 -4
- package/rules/prefer-default-parameters.js +1 -2
- package/rules/prefer-dom-node-append.js +2 -2
- package/rules/prefer-dom-node-remove.js +24 -18
- package/rules/prefer-export-from.js +8 -7
- package/rules/prefer-get-or-insert-computed.js +159 -0
- package/rules/prefer-global-this.js +33 -29
- package/rules/prefer-https.js +83 -0
- package/rules/prefer-includes-over-repeated-comparisons.js +199 -0
- package/rules/prefer-iterator-concat.js +174 -0
- package/rules/prefer-iterator-to-array-at-end.js +123 -0
- package/rules/prefer-keyboard-event-key.js +202 -76
- package/rules/prefer-logical-operator-over-ternary.js +1 -1
- package/rules/prefer-math-abs.js +397 -0
- package/rules/prefer-math-min-max.js +54 -26
- package/rules/prefer-module.js +5 -7
- package/rules/prefer-native-coercion-functions.js +8 -1
- package/rules/prefer-node-protocol.js +7 -4
- package/rules/prefer-number-properties.js +2 -0
- package/rules/prefer-object-from-entries.js +12 -7
- package/rules/prefer-prototype-methods.js +1 -3
- package/rules/prefer-query-selector.js +119 -7
- package/rules/prefer-queue-microtask.js +204 -0
- package/rules/prefer-regexp-test.js +166 -20
- package/rules/prefer-set-has.js +474 -47
- package/rules/prefer-simple-condition-first.js +282 -0
- package/rules/prefer-single-call.js +129 -38
- package/rules/prefer-split-limit.js +107 -0
- package/rules/prefer-spread.js +150 -19
- package/rules/prefer-string-match-all.js +352 -0
- package/rules/prefer-string-pad-start-end.js +380 -0
- package/rules/prefer-string-raw.js +90 -19
- package/rules/prefer-string-repeat.js +173 -0
- package/rules/prefer-string-replace-all.js +180 -12
- package/rules/prefer-string-slice.js +55 -4
- package/rules/prefer-string-starts-ends-with.js +2 -2
- package/rules/prefer-structured-clone.js +1 -0
- package/rules/prefer-switch.js +2 -0
- package/rules/prefer-ternary.js +3 -2
- package/rules/prefer-top-level-await.js +168 -6
- package/rules/prevent-abbreviations.js +144 -158
- package/rules/relative-url-style.js +1 -0
- package/rules/require-css-escape.js +141 -0
- package/rules/require-module-attributes.js +16 -18
- package/rules/require-module-specifiers.js +62 -0
- package/rules/require-passive-events.js +292 -0
- package/rules/rule/to-eslint-rule.js +1 -1
- package/rules/rule/to-eslint-rules.js +4 -6
- package/rules/shared/abbreviations.js +1 -0
- package/rules/shared/dom-events.js +7 -7
- package/rules/shared/identifier-checks.js +205 -0
- package/rules/shared/package-json.js +1 -1
- package/rules/string-content.js +35 -5
- package/rules/switch-case-braces.js +2 -3
- package/rules/switch-case-break-position.js +138 -0
- package/rules/template-indent.js +59 -3
- package/rules/text-encoding-identifier-case.js +23 -5
- package/rules/throw-new-error.js +4 -0
- package/rules/try-complexity.js +184 -0
- package/rules/utils/assert-token.js +3 -5
- package/rules/utils/boolean.js +37 -28
- package/rules/utils/create-deprecated-rules.js +25 -27
- package/rules/utils/get-call-expression-arguments-text.js +3 -5
- package/rules/utils/get-duplicate-array-elements.js +77 -0
- package/rules/utils/index.js +4 -1
- package/rules/utils/is-node-contains-lexical-this.js +65 -0
- package/rules/utils/is-number.js +2 -2
- package/rules/utils/is-same-reference.js +25 -17
- package/rules/utils/should-add-parentheses-to-await-expression-argument.js +9 -9
- package/rules/utils/should-add-parentheses-to-call-expression-callee.js +12 -10
- package/rules/utils/should-add-parentheses-to-conditional-expression-child.js +9 -5
- package/rules/utils/should-add-parentheses-to-expression-statement-expression.js +1 -1
- package/rules/utils/should-add-parentheses-to-logical-expression-child.js +12 -8
- package/rules/utils/should-add-parentheses-to-member-expression-object.js +1 -1
- package/rules/utils/should-add-parentheses-to-unary-expression.js +10 -10
- package/rules/better-regex.js +0 -145
- package/rules/prefer-dom-node-dataset.js +0 -135
- package/rules/prefer-json-parse-buffer.js +0 -161
package/rules/utils/boolean.js
CHANGED
|
@@ -15,48 +15,57 @@ const isVueBooleanAttributeValue = node =>
|
|
|
15
15
|
&& node.parent.value === node
|
|
16
16
|
&& node.parent.key.type === 'VDirectiveKey'
|
|
17
17
|
&& node.parent.key.name.type === 'VIdentifier'
|
|
18
|
-
&&
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
);
|
|
18
|
+
&& [
|
|
19
|
+
'if',
|
|
20
|
+
'else-if',
|
|
21
|
+
'show',
|
|
22
|
+
].includes(node.parent.key.name.rawName);
|
|
23
|
+
const isDirectControlFlowTest = node =>
|
|
24
|
+
[
|
|
25
|
+
'IfStatement',
|
|
26
|
+
'ConditionalExpression',
|
|
27
|
+
'WhileStatement',
|
|
28
|
+
'DoWhileStatement',
|
|
29
|
+
'ForStatement',
|
|
30
|
+
].includes(node.parent.type)
|
|
31
|
+
&& node.parent.test === node;
|
|
32
|
+
const isDirectBooleanExpression = node =>
|
|
33
|
+
isLogicNot(node)
|
|
34
|
+
|| isLogicNotArgument(node)
|
|
35
|
+
|| isBooleanCall(node)
|
|
36
|
+
|| isBooleanCallArgument(node);
|
|
23
37
|
|
|
24
38
|
/**
|
|
25
|
-
Check if the value of node is a `boolean`.
|
|
39
|
+
Check if the expression value of `node` is a `boolean`.
|
|
26
40
|
|
|
27
41
|
@param {Node} node
|
|
28
42
|
@returns {boolean}
|
|
29
43
|
*/
|
|
30
|
-
export function
|
|
31
|
-
if (
|
|
32
|
-
isLogicNot(node)
|
|
33
|
-
|| isLogicNotArgument(node)
|
|
34
|
-
|| isBooleanCall(node)
|
|
35
|
-
|| isBooleanCallArgument(node)
|
|
36
|
-
) {
|
|
44
|
+
export function isBooleanExpression(node) {
|
|
45
|
+
if (isDirectBooleanExpression(node)) {
|
|
37
46
|
return true;
|
|
38
47
|
}
|
|
39
48
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return true;
|
|
49
|
+
if (isLogicalExpression(node.parent)) {
|
|
50
|
+
return isBooleanExpression(node.parent);
|
|
43
51
|
}
|
|
44
52
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
Check if `node` is used as a control-flow test.
|
|
58
|
+
|
|
59
|
+
@param {Node} node
|
|
60
|
+
@returns {boolean}
|
|
61
|
+
*/
|
|
62
|
+
export function isControlFlowTest(node) {
|
|
63
|
+
if (isVueBooleanAttributeValue(node.parent) || isDirectControlFlowTest(node)) {
|
|
55
64
|
return true;
|
|
56
65
|
}
|
|
57
66
|
|
|
58
|
-
if (isLogicalExpression(parent)) {
|
|
59
|
-
return
|
|
67
|
+
if (isLogicalExpression(node.parent)) {
|
|
68
|
+
return isControlFlowTest(node.parent);
|
|
60
69
|
}
|
|
61
70
|
|
|
62
71
|
return false;
|
|
@@ -1,36 +1,34 @@
|
|
|
1
|
-
import getDocumentationUrl from './get-documentation-url.js';
|
|
2
1
|
import packageJson from '../../package.json' with {type: 'json'};
|
|
2
|
+
import getDocumentationUrl from './get-documentation-url.js';
|
|
3
3
|
|
|
4
4
|
const repoUrl = 'https://github.com/sindresorhus/eslint-plugin-unicorn';
|
|
5
5
|
|
|
6
6
|
/** @returns {{ [ruleName: string]: import('eslint').Rule.RuleModule }} */
|
|
7
7
|
export default function createDeprecatedRules(rules) {
|
|
8
|
-
return Object.fromEntries(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
})),
|
|
30
|
-
},
|
|
8
|
+
return Object.fromEntries(Object.entries(rules).map(([ruleId, deprecatedInfo]) => {
|
|
9
|
+
const url = `${repoUrl}/blob/v${packageJson.version}/docs/deleted-and-deprecated-rules.md#${ruleId}`;
|
|
10
|
+
return [
|
|
11
|
+
ruleId,
|
|
12
|
+
{
|
|
13
|
+
// eslint-disable-next-line internal/prefer-context-on
|
|
14
|
+
create: () => ({}),
|
|
15
|
+
meta: {
|
|
16
|
+
docs: {
|
|
17
|
+
description: deprecatedInfo.message,
|
|
18
|
+
url,
|
|
19
|
+
},
|
|
20
|
+
deprecated: {
|
|
21
|
+
message: deprecatedInfo.message,
|
|
22
|
+
url,
|
|
23
|
+
replacedBy: deprecatedInfo.replacedBy.map(replacementRuleId => ({
|
|
24
|
+
rule: {
|
|
25
|
+
name: replacementRuleId,
|
|
26
|
+
url: getDocumentationUrl(replacementRuleId),
|
|
27
|
+
},
|
|
28
|
+
})),
|
|
31
29
|
},
|
|
32
30
|
},
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
);
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
}));
|
|
36
34
|
}
|
|
@@ -26,11 +26,9 @@ export default function getCallExpressionArgumentsText(
|
|
|
26
26
|
} = getCallExpressionTokens(callExpression, context);
|
|
27
27
|
|
|
28
28
|
const [, start] = sourceCode.getRange(openingParenthesisToken);
|
|
29
|
-
const [end] = sourceCode.getRange(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
: (trailingCommaToken ?? closingParenthesisToken),
|
|
33
|
-
);
|
|
29
|
+
const [end] = sourceCode.getRange(includeTrailingComma
|
|
30
|
+
? closingParenthesisToken
|
|
31
|
+
: (trailingCommaToken ?? closingParenthesisToken));
|
|
34
32
|
|
|
35
33
|
return sourceCode.text.slice(start, end);
|
|
36
34
|
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {getStaticValue} from '@eslint-community/eslint-utils';
|
|
2
|
+
import isSameReference from './is-same-reference.js';
|
|
3
|
+
|
|
4
|
+
export const isComparableStaticValue = value =>
|
|
5
|
+
value === null
|
|
6
|
+
|| (
|
|
7
|
+
typeof value !== 'object'
|
|
8
|
+
&& typeof value !== 'function'
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
const isSameValueZero = (left, right) =>
|
|
12
|
+
left === right
|
|
13
|
+
|| (
|
|
14
|
+
typeof left === 'number'
|
|
15
|
+
&& typeof right === 'number'
|
|
16
|
+
&& Number.isNaN(left)
|
|
17
|
+
&& Number.isNaN(right)
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const getComparableStaticElementValueResult = (element, context) => {
|
|
21
|
+
if (!element) {
|
|
22
|
+
return {value: undefined};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const {sourceCode} = context;
|
|
26
|
+
const result = getStaticValue(element, sourceCode.getScope(element));
|
|
27
|
+
|
|
28
|
+
if (!result || !isComparableStaticValue(result.value)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {value: result.value};
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const isDuplicateValue = (leftElement, rightElement, context) => {
|
|
36
|
+
const leftStaticValueResult = getComparableStaticElementValueResult(leftElement, context);
|
|
37
|
+
const rightStaticValueResult = getComparableStaticElementValueResult(rightElement, context);
|
|
38
|
+
|
|
39
|
+
if (
|
|
40
|
+
leftStaticValueResult
|
|
41
|
+
&& rightStaticValueResult
|
|
42
|
+
) {
|
|
43
|
+
return isSameValueZero(leftStaticValueResult.value, rightStaticValueResult.value);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (
|
|
47
|
+
!leftElement
|
|
48
|
+
|| !rightElement
|
|
49
|
+
|| leftElement.type === 'Literal'
|
|
50
|
+
|| rightElement.type === 'Literal'
|
|
51
|
+
) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return isSameReference(leftElement, rightElement);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const getDuplicateArrayElements = (elements, context) => {
|
|
59
|
+
const checkedElements = [];
|
|
60
|
+
const duplicateElements = [];
|
|
61
|
+
|
|
62
|
+
for (const element of elements) {
|
|
63
|
+
if (element?.type === 'SpreadElement') {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (checkedElements.some(checkedElement => isDuplicateValue(checkedElement, element, context))) {
|
|
68
|
+
duplicateElements.push(element);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
checkedElements.push(element);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return duplicateElements;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export default getDuplicateArrayElements;
|
package/rules/utils/index.js
CHANGED
|
@@ -16,7 +16,8 @@ export {
|
|
|
16
16
|
} from './is-node-matches.js';
|
|
17
17
|
|
|
18
18
|
export {
|
|
19
|
-
|
|
19
|
+
isBooleanExpression,
|
|
20
|
+
isControlFlowTest,
|
|
20
21
|
getBooleanAncestor,
|
|
21
22
|
} from './boolean.js';
|
|
22
23
|
|
|
@@ -27,6 +28,7 @@ export {default as getClassHeadLocation} from './get-class-head-location.js';
|
|
|
27
28
|
export {default as getAvailableVariableName} from './get-available-variable-name.js';
|
|
28
29
|
export {default as getCallExpressionArgumentsText} from './get-call-expression-arguments-text.js';
|
|
29
30
|
export {getCallExpressionTokens, getNewExpressionTokens} from './get-call-or-new-expression-tokens.js';
|
|
31
|
+
export {default as getDuplicateArrayElements, isComparableStaticValue} from './get-duplicate-array-elements.js';
|
|
30
32
|
export {default as getIndentString} from './get-indent-string.js';
|
|
31
33
|
export {default as getReferences} from './get-references.js';
|
|
32
34
|
export {default as getScopes} from './get-scopes.js';
|
|
@@ -41,6 +43,7 @@ export {default as isNewExpressionWithParentheses} from './is-new-expression-wit
|
|
|
41
43
|
export {default as isNumber} from './is-number.js';
|
|
42
44
|
export {default as isNodeValueNotDomNode} from './is-node-value-not-dom-node.js';
|
|
43
45
|
export {default as isNodeValueNotFunction} from './is-node-value-not-function.js';
|
|
46
|
+
export {default as isNodeContainsLexicalThis} from './is-node-contains-lexical-this.js';
|
|
44
47
|
export {default as isOnSameLine} from './is-on-same-line.js';
|
|
45
48
|
export {default as isSameIdentifier} from './is-same-identifier.js';
|
|
46
49
|
export {default as isSameReference} from './is-same-reference.js';
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Check whether a node subtree contains lexical `this`.
|
|
3
|
+
|
|
4
|
+
This is parser-agnostic and intentionally does not use `scope.thisFound`, because that flag is inconsistent across supported parsers.
|
|
5
|
+
*/
|
|
6
|
+
const isNodeContainsLexicalThis = (node, visitorKeys) => {
|
|
7
|
+
if (node.type === 'ThisExpression') {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (
|
|
12
|
+
node.type === 'FunctionDeclaration'
|
|
13
|
+
|| node.type === 'FunctionExpression'
|
|
14
|
+
) {
|
|
15
|
+
// `this` inside non-arrow functions is rebound and does not affect outer arrows.
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (node.type === 'ClassDeclaration' || node.type === 'ClassExpression') {
|
|
20
|
+
// Class bodies create their own `this`, but computed keys/superclass are evaluated in outer scope.
|
|
21
|
+
if (node.superClass && isNodeContainsLexicalThis(node.superClass, visitorKeys)) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
for (const classElement of node.body.body) {
|
|
26
|
+
if (classElement.computed && isNodeContainsLexicalThis(classElement.key, visitorKeys)) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const keys = visitorKeys[node.type];
|
|
35
|
+
|
|
36
|
+
if (!keys) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
for (const key of keys) {
|
|
41
|
+
const value = node[key];
|
|
42
|
+
|
|
43
|
+
if (!value) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (Array.isArray(value)) {
|
|
48
|
+
for (const childNode of value) {
|
|
49
|
+
if (childNode && isNodeContainsLexicalThis(childNode, visitorKeys)) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (isNodeContainsLexicalThis(value, visitorKeys)) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return false;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export default isNodeContainsLexicalThis;
|
package/rules/utils/is-number.js
CHANGED
|
@@ -200,8 +200,8 @@ export default function isNumber(node, scope) {
|
|
|
200
200
|
if (
|
|
201
201
|
testStaticValueResult !== null
|
|
202
202
|
&& (
|
|
203
|
-
(testStaticValueResult.value
|
|
204
|
-
|| (!testStaticValueResult.value
|
|
203
|
+
(isConsequentNumber && testStaticValueResult.value)
|
|
204
|
+
|| (isAlternateNumber && !testStaticValueResult.value)
|
|
205
205
|
)
|
|
206
206
|
) {
|
|
207
207
|
return true;
|
|
@@ -81,12 +81,10 @@ Check if two literal nodes are the same value.
|
|
|
81
81
|
function equalLiteralValue(left, right) {
|
|
82
82
|
// RegExp literal.
|
|
83
83
|
if (left.regex || right.regex) {
|
|
84
|
-
return Boolean(
|
|
85
|
-
left.regex
|
|
84
|
+
return Boolean(left.regex
|
|
86
85
|
&& right.regex
|
|
87
86
|
&& left.regex.pattern === right.regex.pattern
|
|
88
|
-
&& left.regex.flags === right.regex.flags
|
|
89
|
-
);
|
|
87
|
+
&& left.regex.flags === right.regex.flags);
|
|
90
88
|
}
|
|
91
89
|
|
|
92
90
|
// BigInt literal.
|
|
@@ -97,6 +95,26 @@ function equalLiteralValue(left, right) {
|
|
|
97
95
|
return left.value === right.value;
|
|
98
96
|
}
|
|
99
97
|
|
|
98
|
+
/**
|
|
99
|
+
Unwrap ChainExpression (`?.`) and TypeScript type assertion (`as`, `<Type>`, or `!`) nodes.
|
|
100
|
+
@param {ASTNode} node The node to unwrap.
|
|
101
|
+
@returns {ASTNode} The unwrapped node.
|
|
102
|
+
*/
|
|
103
|
+
function unwrapNode(node) {
|
|
104
|
+
if (
|
|
105
|
+
[
|
|
106
|
+
'ChainExpression',
|
|
107
|
+
'TSAsExpression',
|
|
108
|
+
'TSTypeAssertion',
|
|
109
|
+
'TSNonNullExpression',
|
|
110
|
+
].includes(node.type)
|
|
111
|
+
) {
|
|
112
|
+
return unwrapNode(node.expression);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return node;
|
|
116
|
+
}
|
|
117
|
+
|
|
100
118
|
/**
|
|
101
119
|
Check if two expressions reference the same value. For example:
|
|
102
120
|
a = a
|
|
@@ -108,16 +126,10 @@ Check if two expressions reference the same value. For example:
|
|
|
108
126
|
@returns {boolean} `true` if both sides match and reference the same value.
|
|
109
127
|
*/
|
|
110
128
|
export default function isSameReference(left, right) {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (left.type === 'ChainExpression') {
|
|
114
|
-
return isSameReference(left.expression, right);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (right.type === 'ChainExpression') {
|
|
118
|
-
return isSameReference(left, right.expression);
|
|
119
|
-
}
|
|
129
|
+
left = unwrapNode(left);
|
|
130
|
+
right = unwrapNode(right);
|
|
120
131
|
|
|
132
|
+
if (left.type !== right.type) {
|
|
121
133
|
return false;
|
|
122
134
|
}
|
|
123
135
|
|
|
@@ -136,10 +148,6 @@ export default function isSameReference(left, right) {
|
|
|
136
148
|
return equalLiteralValue(left, right);
|
|
137
149
|
}
|
|
138
150
|
|
|
139
|
-
case 'ChainExpression': {
|
|
140
|
-
return isSameReference(left.expression, right.expression);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
151
|
case 'MemberExpression': {
|
|
144
152
|
const nameA = getStaticPropertyName(left);
|
|
145
153
|
|
|
@@ -5,13 +5,13 @@ Check if parentheses should be added to a `node` when it's used as `argument` of
|
|
|
5
5
|
@returns {boolean}
|
|
6
6
|
*/
|
|
7
7
|
export default function shouldAddParenthesesToAwaitExpressionArgument(node) {
|
|
8
|
-
return
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
);
|
|
8
|
+
return [
|
|
9
|
+
'SequenceExpression',
|
|
10
|
+
'YieldExpression',
|
|
11
|
+
'ArrowFunctionExpression',
|
|
12
|
+
'ConditionalExpression',
|
|
13
|
+
'AssignmentExpression',
|
|
14
|
+
'LogicalExpression',
|
|
15
|
+
'BinaryExpression',
|
|
16
|
+
].includes(node.type);
|
|
17
17
|
}
|
|
@@ -5,14 +5,16 @@ Check if parentheses should be added to a `node` when it's used as `callee` of `
|
|
|
5
5
|
@returns {boolean}
|
|
6
6
|
*/
|
|
7
7
|
export default function shouldAddParenthesesToCallExpressionCallee(node) {
|
|
8
|
-
return
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
return [
|
|
9
|
+
'SequenceExpression',
|
|
10
|
+
'YieldExpression',
|
|
11
|
+
'ArrowFunctionExpression',
|
|
12
|
+
'ConditionalExpression',
|
|
13
|
+
'AssignmentExpression',
|
|
14
|
+
'LogicalExpression',
|
|
15
|
+
'BinaryExpression',
|
|
16
|
+
'UnaryExpression',
|
|
17
|
+
'UpdateExpression',
|
|
18
|
+
'NewExpression',
|
|
19
|
+
].includes(node.type);
|
|
18
20
|
}
|
|
@@ -5,9 +5,13 @@ Check if parentheses should be added to a `node` when it's used as child of `Con
|
|
|
5
5
|
@returns {boolean}
|
|
6
6
|
*/
|
|
7
7
|
export default function shouldAddParenthesesToConditionalExpressionChild(node) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
// Lower precedence, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table
|
|
9
|
+
return [
|
|
10
|
+
'AwaitExpression',
|
|
11
|
+
'AssignmentExpression',
|
|
12
|
+
'YieldExpression',
|
|
13
|
+
'SequenceExpression',
|
|
14
|
+
'TSAsExpression',
|
|
15
|
+
'TSTypeAssertion',
|
|
16
|
+
].includes(node.type);
|
|
13
17
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
Check if parentheses should
|
|
2
|
+
Check if parentheses should be added to a `node` when it's used as an `expression` of `ExpressionStatement`.
|
|
3
3
|
|
|
4
4
|
@param {Node} node - The AST node to check.
|
|
5
5
|
@param {SourceCode} sourceCode - The source code object.
|
|
@@ -20,8 +20,10 @@ export default function shouldAddParenthesesToLogicalExpressionChild(node, {oper
|
|
|
20
20
|
|
|
21
21
|
// Not really needed, but more readable
|
|
22
22
|
if (
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
[
|
|
24
|
+
'AwaitExpression',
|
|
25
|
+
'BinaryExpression',
|
|
26
|
+
].includes(node.type)
|
|
25
27
|
) {
|
|
26
28
|
return true;
|
|
27
29
|
}
|
|
@@ -29,12 +31,14 @@ export default function shouldAddParenthesesToLogicalExpressionChild(node, {oper
|
|
|
29
31
|
// Lower precedence than `LogicalExpression`
|
|
30
32
|
// see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table
|
|
31
33
|
if (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
[
|
|
35
|
+
'LogicalExpression',
|
|
36
|
+
'ConditionalExpression',
|
|
37
|
+
'AssignmentExpression',
|
|
38
|
+
'ArrowFunctionExpression',
|
|
39
|
+
'YieldExpression',
|
|
40
|
+
'SequenceExpression',
|
|
41
|
+
].includes(node.type)
|
|
38
42
|
) {
|
|
39
43
|
return true;
|
|
40
44
|
}
|
|
@@ -6,7 +6,7 @@ import {isDecimalIntegerNode} from './numeric.js';
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
Check if parentheses should
|
|
9
|
+
Check if parentheses should be added to a `node` when it's used as an `object` of `MemberExpression`.
|
|
10
10
|
|
|
11
11
|
@param {ESTree.Node} node - The AST node to check.
|
|
12
12
|
@param {ESLint.Rule.RuleContext} context - The ESLint rule context object.
|
|
@@ -11,14 +11,14 @@ export default function shouldAddParenthesesToUnaryExpressionArgument(node, oper
|
|
|
11
11
|
throw new Error('Unexpected operator');
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
return
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
);
|
|
14
|
+
return [
|
|
15
|
+
'UpdateExpression',
|
|
16
|
+
'BinaryExpression',
|
|
17
|
+
'LogicalExpression',
|
|
18
|
+
'ConditionalExpression',
|
|
19
|
+
'AssignmentExpression',
|
|
20
|
+
'ArrowFunctionExpression',
|
|
21
|
+
'YieldExpression',
|
|
22
|
+
'SequenceExpression',
|
|
23
|
+
].includes(node.type);
|
|
24
24
|
}
|