@typescript-eslint/eslint-plugin 6.0.0-alpha.98 → 6.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/README.md +2 -0
- package/dist/configs/all.js +2 -0
- package/dist/configs/all.js.map +1 -1
- package/dist/configs/disable-type-checked.js +3 -0
- package/dist/configs/disable-type-checked.js.map +1 -1
- package/dist/configs/recommended-type-checked.js +6 -0
- package/dist/configs/recommended-type-checked.js.map +1 -1
- package/dist/configs/recommended.js +2 -0
- package/dist/configs/recommended.js.map +1 -1
- package/dist/configs/strict-type-checked.js +4 -0
- package/dist/configs/strict-type-checked.js.map +1 -1
- package/dist/configs/stylistic-type-checked.js +0 -1
- package/dist/configs/stylistic-type-checked.js.map +1 -1
- package/dist/configs/stylistic.js +0 -2
- package/dist/configs/stylistic.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/rules/array-type.js +19 -20
- package/dist/rules/array-type.js.map +1 -1
- package/dist/rules/ban-ts-comment.js +33 -35
- package/dist/rules/ban-ts-comment.js.map +1 -1
- package/dist/rules/ban-types.js +75 -14
- package/dist/rules/ban-types.js.map +1 -1
- package/dist/rules/class-literal-property-style.js +38 -21
- package/dist/rules/class-literal-property-style.js.map +1 -1
- package/dist/rules/comma-dangle.js +4 -2
- package/dist/rules/comma-dangle.js.map +1 -1
- package/dist/rules/comma-spacing.js +5 -0
- package/dist/rules/comma-spacing.js.map +1 -1
- package/dist/rules/consistent-generic-constructors.js +1 -0
- package/dist/rules/consistent-generic-constructors.js.map +1 -1
- package/dist/rules/consistent-indexed-object-style.js +1 -0
- package/dist/rules/consistent-indexed-object-style.js.map +1 -1
- package/dist/rules/consistent-type-assertions.js +49 -0
- package/dist/rules/consistent-type-assertions.js.map +1 -1
- package/dist/rules/consistent-type-definitions.js +1 -0
- package/dist/rules/consistent-type-definitions.js.map +1 -1
- package/dist/rules/consistent-type-exports.js +1 -0
- package/dist/rules/consistent-type-exports.js.map +1 -1
- package/dist/rules/consistent-type-imports.js +2 -0
- package/dist/rules/consistent-type-imports.js.map +1 -1
- package/dist/rules/enum-utils/shared.js +61 -0
- package/dist/rules/enum-utils/shared.js.map +1 -0
- package/dist/rules/explicit-function-return-type.js.map +1 -1
- package/dist/rules/explicit-member-accessibility.js +43 -44
- package/dist/rules/explicit-member-accessibility.js.map +1 -1
- package/dist/rules/explicit-module-boundary-types.js +1 -1
- package/dist/rules/explicit-module-boundary-types.js.map +1 -1
- package/dist/rules/func-call-spacing.js +2 -0
- package/dist/rules/func-call-spacing.js.map +1 -1
- package/dist/rules/indent.js.map +1 -1
- package/dist/rules/index.js +4 -0
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/key-spacing.js.map +1 -1
- package/dist/rules/keyword-spacing.js.map +1 -1
- package/dist/rules/lines-around-comment.js +78 -81
- package/dist/rules/lines-around-comment.js.map +1 -1
- package/dist/rules/lines-between-class-members.js +7 -5
- package/dist/rules/lines-between-class-members.js.map +1 -1
- package/dist/rules/member-delimiter-style.js +45 -27
- package/dist/rules/member-delimiter-style.js.map +1 -1
- package/dist/rules/member-ordering.js +55 -66
- package/dist/rules/member-ordering.js.map +1 -1
- package/dist/rules/method-signature-style.js +1 -0
- package/dist/rules/method-signature-style.js.map +1 -1
- package/dist/rules/naming-convention-utils/enums.js +6 -12
- package/dist/rules/naming-convention-utils/enums.js.map +1 -1
- package/dist/rules/naming-convention-utils/schema.js +50 -25
- package/dist/rules/naming-convention-utils/schema.js.map +1 -1
- package/dist/rules/naming-convention.js.map +1 -1
- package/dist/rules/no-base-to-string.js +2 -2
- package/dist/rules/no-base-to-string.js.map +1 -1
- package/dist/rules/no-confusing-void-expression.js +1 -0
- package/dist/rules/no-confusing-void-expression.js.map +1 -1
- package/dist/rules/no-duplicate-type-constituents.js +161 -0
- package/dist/rules/no-duplicate-type-constituents.js.map +1 -0
- package/dist/rules/no-empty-function.js +1 -0
- package/dist/rules/no-empty-function.js.map +1 -1
- package/dist/rules/no-empty-interface.js +2 -1
- package/dist/rules/no-empty-interface.js.map +1 -1
- package/dist/rules/no-explicit-any.js +1 -1
- package/dist/rules/no-explicit-any.js.map +1 -1
- package/dist/rules/no-extraneous-class.js +2 -3
- package/dist/rules/no-extraneous-class.js.map +1 -1
- package/dist/rules/no-implied-eval.js +1 -0
- package/dist/rules/no-implied-eval.js.map +1 -1
- package/dist/rules/no-inferrable-types.js.map +1 -1
- package/dist/rules/no-invalid-void-type.js +1 -1
- package/dist/rules/no-invalid-void-type.js.map +1 -1
- package/dist/rules/no-loop-func.js.map +1 -1
- package/dist/rules/no-magic-numbers.js.map +1 -1
- package/dist/rules/no-misused-promises.js +3 -2
- package/dist/rules/no-misused-promises.js.map +1 -1
- package/dist/rules/no-redeclare.js +2 -1
- package/dist/rules/no-redeclare.js.map +1 -1
- package/dist/rules/no-redundant-type-constituents.js +2 -0
- package/dist/rules/no-redundant-type-constituents.js.map +1 -1
- package/dist/rules/no-restricted-imports.js +80 -21
- package/dist/rules/no-restricted-imports.js.map +1 -1
- package/dist/rules/no-shadow.js +2 -1
- package/dist/rules/no-shadow.js.map +1 -1
- package/dist/rules/no-type-alias.js +24 -15
- package/dist/rules/no-type-alias.js.map +1 -1
- package/dist/rules/no-unnecessary-condition.js +2 -2
- package/dist/rules/no-unnecessary-condition.js.map +1 -1
- package/dist/rules/no-unnecessary-qualifier.js.map +1 -1
- package/dist/rules/no-unnecessary-type-assertion.js +1 -0
- package/dist/rules/no-unnecessary-type-assertion.js.map +1 -1
- package/dist/rules/no-unsafe-argument.js +3 -3
- package/dist/rules/no-unsafe-argument.js.map +1 -1
- package/dist/rules/no-unsafe-declaration-merging.js +1 -1
- package/dist/rules/no-unsafe-declaration-merging.js.map +1 -1
- package/dist/rules/no-unsafe-enum-comparison.js +119 -0
- package/dist/rules/no-unsafe-enum-comparison.js.map +1 -0
- package/dist/rules/no-unused-vars.js +4 -0
- package/dist/rules/no-unused-vars.js.map +1 -1
- package/dist/rules/no-use-before-define.js +1 -0
- package/dist/rules/no-use-before-define.js.map +1 -1
- package/dist/rules/padding-line-between-statements.js +11 -3
- package/dist/rules/padding-line-between-statements.js.map +1 -1
- package/dist/rules/parameter-properties.js +29 -30
- package/dist/rules/parameter-properties.js.map +1 -1
- package/dist/rules/prefer-includes.js +21 -5
- package/dist/rules/prefer-includes.js.map +1 -1
- package/dist/rules/prefer-nullish-coalescing.js +82 -63
- package/dist/rules/prefer-nullish-coalescing.js.map +1 -1
- package/dist/rules/prefer-optional-chain-utils/PreferOptionalChainOptions.js +3 -0
- package/dist/rules/prefer-optional-chain-utils/PreferOptionalChainOptions.js.map +1 -0
- package/dist/rules/prefer-optional-chain-utils/analyzeChain.js +419 -0
- package/dist/rules/prefer-optional-chain-utils/analyzeChain.js.map +1 -0
- package/dist/rules/prefer-optional-chain-utils/compareNodes.js +318 -0
- package/dist/rules/prefer-optional-chain-utils/compareNodes.js.map +1 -0
- package/dist/rules/prefer-optional-chain-utils/gatherLogicalOperands.js +281 -0
- package/dist/rules/prefer-optional-chain-utils/gatherLogicalOperands.js.map +1 -0
- package/dist/rules/prefer-optional-chain.js +80 -391
- package/dist/rules/prefer-optional-chain.js.map +1 -1
- package/dist/rules/prefer-readonly.js +1 -1
- package/dist/rules/prefer-readonly.js.map +1 -1
- package/dist/rules/prefer-regexp-exec.js +7 -1
- package/dist/rules/prefer-regexp-exec.js.map +1 -1
- package/dist/rules/require-array-sort-compare.js +3 -2
- package/dist/rules/require-array-sort-compare.js.map +1 -1
- package/dist/rules/restrict-plus-operands.js +132 -96
- package/dist/rules/restrict-plus-operands.js.map +1 -1
- package/dist/rules/restrict-template-expressions.js +11 -6
- package/dist/rules/restrict-template-expressions.js.map +1 -1
- package/dist/rules/return-await.js +1 -0
- package/dist/rules/return-await.js.map +1 -1
- package/dist/rules/sort-type-constituents.js +1 -1
- package/dist/rules/sort-type-constituents.js.map +1 -1
- package/dist/rules/space-before-function-paren.js +4 -0
- package/dist/rules/space-before-function-paren.js.map +1 -1
- package/dist/rules/strict-boolean-expressions.js +7 -2
- package/dist/rules/strict-boolean-expressions.js.map +1 -1
- package/dist/rules/switch-exhaustiveness-check.js.map +1 -1
- package/dist/rules/triple-slash-reference.js +3 -0
- package/dist/rules/triple-slash-reference.js.map +1 -1
- package/dist/rules/type-annotation-spacing.js +16 -14
- package/dist/rules/type-annotation-spacing.js.map +1 -1
- package/dist/rules/typedef.js +1 -0
- package/dist/rules/typedef.js.map +1 -1
- package/dist/rules/unbound-method.js +1 -0
- package/dist/rules/unbound-method.js.map +1 -1
- package/dist/rules/unified-signatures.js +3 -3
- package/dist/rules/unified-signatures.js.map +1 -1
- package/dist/util/astUtils.js.map +1 -1
- package/dist/util/collectUnusedVariables.js +1 -1
- package/dist/util/collectUnusedVariables.js.map +1 -1
- package/dist/util/getOperatorPrecedence.js +112 -2
- package/dist/util/getOperatorPrecedence.js.map +1 -1
- package/dist/util/getStringLength.js +2 -2
- package/dist/util/getStringLength.js.map +1 -1
- package/dist/util/misc.js +1 -2
- package/dist/util/misc.js.map +1 -1
- package/docs/rules/README.md +2 -2
- package/docs/rules/ban-types.md +10 -0
- package/docs/rules/comma-dangle.md +1 -1
- package/docs/rules/explicit-module-boundary-types.md +1 -1
- package/docs/rules/lines-around-comment.md +3 -13
- package/docs/rules/naming-convention.md +63 -63
- package/docs/rules/no-duplicate-type-constituents.md +61 -0
- package/docs/rules/no-unnecessary-boolean-literal-compare.md +10 -10
- package/docs/rules/no-unnecessary-type-constraint.md +6 -2
- package/docs/rules/no-unsafe-enum-comparison.md +77 -0
- package/docs/rules/prefer-includes.md +1 -1
- package/docs/rules/prefer-nullish-coalescing.md +23 -0
- package/docs/rules/prefer-optional-chain.md +195 -4
- package/docs/rules/require-await.md +0 -2
- package/docs/rules/restrict-plus-operands.md +135 -25
- package/docs/rules/restrict-template-expressions.md +15 -3
- package/docs/rules/sort-type-constituents.md +3 -3
- package/docs/rules/triple-slash-reference.md +0 -2
- package/docs/rules/type-annotation-spacing.md +22 -8
- package/docs/rules/unified-signatures.md +0 -2
- package/package.json +22 -15
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.compareNodes = void 0;
|
|
4
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
5
|
+
const visitor_keys_1 = require("@typescript-eslint/visitor-keys");
|
|
6
|
+
function compareArrays(arrayA, arrayB) {
|
|
7
|
+
if (arrayA.length !== arrayB.length) {
|
|
8
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
9
|
+
}
|
|
10
|
+
const result = arrayA.every((elA, idx) => {
|
|
11
|
+
const elB = arrayB[idx];
|
|
12
|
+
if (elA == null || elB == null) {
|
|
13
|
+
return elA === elB;
|
|
14
|
+
}
|
|
15
|
+
return compareUnknownValues(elA, elB) === "Equal" /* NodeComparisonResult.Equal */;
|
|
16
|
+
});
|
|
17
|
+
if (result) {
|
|
18
|
+
return "Equal" /* NodeComparisonResult.Equal */;
|
|
19
|
+
}
|
|
20
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
21
|
+
}
|
|
22
|
+
function isValidNode(x) {
|
|
23
|
+
return (typeof x === 'object' &&
|
|
24
|
+
x != null &&
|
|
25
|
+
'type' in x &&
|
|
26
|
+
typeof x.type === 'string');
|
|
27
|
+
}
|
|
28
|
+
function isValidChainExpressionToLookThrough(node) {
|
|
29
|
+
return (!(node.parent?.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
30
|
+
node.parent.object === node) &&
|
|
31
|
+
!(node.parent?.type === utils_1.AST_NODE_TYPES.CallExpression &&
|
|
32
|
+
node.parent.callee === node) &&
|
|
33
|
+
node.type === utils_1.AST_NODE_TYPES.ChainExpression);
|
|
34
|
+
}
|
|
35
|
+
function compareUnknownValues(valueA, valueB) {
|
|
36
|
+
/* istanbul ignore if -- not possible for us to test this - it's just a sanity safeguard */
|
|
37
|
+
if (valueA == null || valueB == null) {
|
|
38
|
+
if (valueA !== valueB) {
|
|
39
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
40
|
+
}
|
|
41
|
+
return "Equal" /* NodeComparisonResult.Equal */;
|
|
42
|
+
}
|
|
43
|
+
/* istanbul ignore if -- not possible for us to test this - it's just a sanity safeguard */
|
|
44
|
+
if (!isValidNode(valueA) || !isValidNode(valueB)) {
|
|
45
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
46
|
+
}
|
|
47
|
+
return compareNodes(valueA, valueB);
|
|
48
|
+
}
|
|
49
|
+
function compareByVisiting(nodeA, nodeB) {
|
|
50
|
+
const currentVisitorKeys = visitor_keys_1.visitorKeys[nodeA.type];
|
|
51
|
+
/* istanbul ignore if -- not possible for us to test this - it's just a sanity safeguard */
|
|
52
|
+
if (currentVisitorKeys == null) {
|
|
53
|
+
// we don't know how to visit this node, so assume it's invalid to avoid false-positives / broken fixers
|
|
54
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
55
|
+
}
|
|
56
|
+
if (currentVisitorKeys.length === 0) {
|
|
57
|
+
// assume nodes with no keys are constant things like keywords
|
|
58
|
+
return "Equal" /* NodeComparisonResult.Equal */;
|
|
59
|
+
}
|
|
60
|
+
for (const key of currentVisitorKeys) {
|
|
61
|
+
// @ts-expect-error - dynamic access but it's safe
|
|
62
|
+
const nodeAChildOrChildren = nodeA[key];
|
|
63
|
+
// @ts-expect-error - dynamic access but it's safe
|
|
64
|
+
const nodeBChildOrChildren = nodeB[key];
|
|
65
|
+
if (Array.isArray(nodeAChildOrChildren)) {
|
|
66
|
+
const arrayA = nodeAChildOrChildren;
|
|
67
|
+
const arrayB = nodeBChildOrChildren;
|
|
68
|
+
const result = compareArrays(arrayA, arrayB);
|
|
69
|
+
if (result !== "Equal" /* NodeComparisonResult.Equal */) {
|
|
70
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
71
|
+
}
|
|
72
|
+
// fallthrough to the next key as the key was "equal"
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const result = compareUnknownValues(nodeAChildOrChildren, nodeBChildOrChildren);
|
|
76
|
+
if (result !== "Equal" /* NodeComparisonResult.Equal */) {
|
|
77
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
78
|
+
}
|
|
79
|
+
// fallthrough to the next key as the key was "equal"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return "Equal" /* NodeComparisonResult.Equal */;
|
|
83
|
+
}
|
|
84
|
+
function compareNodesUncached(nodeA, nodeB) {
|
|
85
|
+
if (nodeA.type !== nodeB.type) {
|
|
86
|
+
// special cases where nodes are allowed to be non-equal
|
|
87
|
+
// look through a chain expression node at the top-level because it only
|
|
88
|
+
// exists to delimit the end of an optional chain
|
|
89
|
+
//
|
|
90
|
+
// a?.b && a.b.c
|
|
91
|
+
// ^^^^ ChainExpression, MemberExpression
|
|
92
|
+
// ^^^^^ MemberExpression
|
|
93
|
+
//
|
|
94
|
+
// except for in this class of cases
|
|
95
|
+
// (a?.b).c && a.b.c
|
|
96
|
+
// because the parentheses have runtime meaning (sad face)
|
|
97
|
+
if (isValidChainExpressionToLookThrough(nodeA)) {
|
|
98
|
+
return compareNodes(nodeA.expression, nodeB);
|
|
99
|
+
}
|
|
100
|
+
if (isValidChainExpressionToLookThrough(nodeB)) {
|
|
101
|
+
return compareNodes(nodeA, nodeB.expression);
|
|
102
|
+
}
|
|
103
|
+
// look through the type-only non-null assertion because its existence could
|
|
104
|
+
// possibly be replaced by an optional chain instead
|
|
105
|
+
//
|
|
106
|
+
// a.b! && a.b.c
|
|
107
|
+
// ^^^^ TSNonNullExpression
|
|
108
|
+
if (nodeA.type === utils_1.AST_NODE_TYPES.TSNonNullExpression) {
|
|
109
|
+
return compareNodes(nodeA.expression, nodeB);
|
|
110
|
+
}
|
|
111
|
+
if (nodeB.type === utils_1.AST_NODE_TYPES.TSNonNullExpression) {
|
|
112
|
+
return compareNodes(nodeA, nodeB.expression);
|
|
113
|
+
}
|
|
114
|
+
// special case for subset optional chains where the node types don't match,
|
|
115
|
+
// but we want to try comparing by discarding the "extra" code
|
|
116
|
+
//
|
|
117
|
+
// a && a.b
|
|
118
|
+
// ^ compare this
|
|
119
|
+
// a && a()
|
|
120
|
+
// ^ compare this
|
|
121
|
+
// a.b && a.b()
|
|
122
|
+
// ^^^ compare this
|
|
123
|
+
// a() && a().b
|
|
124
|
+
// ^^^ compare this
|
|
125
|
+
// import.meta && import.meta.b
|
|
126
|
+
// ^^^^^^^^^^^ compare this
|
|
127
|
+
if (nodeA.type === utils_1.AST_NODE_TYPES.CallExpression ||
|
|
128
|
+
nodeA.type === utils_1.AST_NODE_TYPES.Identifier ||
|
|
129
|
+
nodeA.type === utils_1.AST_NODE_TYPES.MemberExpression ||
|
|
130
|
+
nodeA.type === utils_1.AST_NODE_TYPES.MetaProperty) {
|
|
131
|
+
switch (nodeB.type) {
|
|
132
|
+
case utils_1.AST_NODE_TYPES.MemberExpression:
|
|
133
|
+
if (nodeB.property.type === utils_1.AST_NODE_TYPES.PrivateIdentifier) {
|
|
134
|
+
// Private identifiers in optional chaining is not currently allowed
|
|
135
|
+
// TODO - handle this once TS supports it (https://github.com/microsoft/TypeScript/issues/42734)
|
|
136
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
137
|
+
}
|
|
138
|
+
if (compareNodes(nodeA, nodeB.object) !== "Invalid" /* NodeComparisonResult.Invalid */) {
|
|
139
|
+
return "Subset" /* NodeComparisonResult.Subset */;
|
|
140
|
+
}
|
|
141
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
142
|
+
case utils_1.AST_NODE_TYPES.CallExpression:
|
|
143
|
+
if (compareNodes(nodeA, nodeB.callee) !== "Invalid" /* NodeComparisonResult.Invalid */) {
|
|
144
|
+
return "Subset" /* NodeComparisonResult.Subset */;
|
|
145
|
+
}
|
|
146
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
147
|
+
default:
|
|
148
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
152
|
+
}
|
|
153
|
+
switch (nodeA.type) {
|
|
154
|
+
// these expressions create a new instance each time - so it makes no sense to compare the chain
|
|
155
|
+
case utils_1.AST_NODE_TYPES.ArrayExpression:
|
|
156
|
+
case utils_1.AST_NODE_TYPES.ArrowFunctionExpression:
|
|
157
|
+
case utils_1.AST_NODE_TYPES.ClassExpression:
|
|
158
|
+
case utils_1.AST_NODE_TYPES.FunctionExpression:
|
|
159
|
+
case utils_1.AST_NODE_TYPES.JSXElement:
|
|
160
|
+
case utils_1.AST_NODE_TYPES.JSXFragment:
|
|
161
|
+
case utils_1.AST_NODE_TYPES.NewExpression:
|
|
162
|
+
case utils_1.AST_NODE_TYPES.ObjectExpression:
|
|
163
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
164
|
+
// chaining from assignments could change the value irrevocably - so it makes no sense to compare the chain
|
|
165
|
+
case utils_1.AST_NODE_TYPES.AssignmentExpression:
|
|
166
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
167
|
+
case utils_1.AST_NODE_TYPES.CallExpression: {
|
|
168
|
+
const nodeBCall = nodeB;
|
|
169
|
+
// check for cases like
|
|
170
|
+
// foo() && foo()(bar)
|
|
171
|
+
// ^^^^^ nodeA
|
|
172
|
+
// ^^^^^^^^^^ nodeB
|
|
173
|
+
// we don't want to check the arguments in this case
|
|
174
|
+
const aSubsetOfB = compareNodes(nodeA, nodeBCall.callee);
|
|
175
|
+
if (aSubsetOfB !== "Invalid" /* NodeComparisonResult.Invalid */) {
|
|
176
|
+
return "Subset" /* NodeComparisonResult.Subset */;
|
|
177
|
+
}
|
|
178
|
+
const calleeCompare = compareNodes(nodeA.callee, nodeBCall.callee);
|
|
179
|
+
if (calleeCompare !== "Equal" /* NodeComparisonResult.Equal */) {
|
|
180
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
181
|
+
}
|
|
182
|
+
// NOTE - we purposely ignore optional flag because for our purposes
|
|
183
|
+
// foo?.bar() && foo.bar?.()?.baz
|
|
184
|
+
// or
|
|
185
|
+
// foo.bar() && foo?.bar?.()?.baz
|
|
186
|
+
// are going to be exactly the same
|
|
187
|
+
const argumentCompare = compareArrays(nodeA.arguments, nodeBCall.arguments);
|
|
188
|
+
if (argumentCompare !== "Equal" /* NodeComparisonResult.Equal */) {
|
|
189
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
190
|
+
}
|
|
191
|
+
const typeParamCompare = compareNodes(nodeA.typeArguments, nodeBCall.typeArguments);
|
|
192
|
+
if (typeParamCompare === "Equal" /* NodeComparisonResult.Equal */) {
|
|
193
|
+
return "Equal" /* NodeComparisonResult.Equal */;
|
|
194
|
+
}
|
|
195
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
196
|
+
}
|
|
197
|
+
case utils_1.AST_NODE_TYPES.ChainExpression:
|
|
198
|
+
// special case handling for ChainExpression because it's allowed to be a subset
|
|
199
|
+
return compareNodes(nodeA, nodeB.expression);
|
|
200
|
+
case utils_1.AST_NODE_TYPES.Identifier:
|
|
201
|
+
case utils_1.AST_NODE_TYPES.PrivateIdentifier:
|
|
202
|
+
if (nodeA.name === nodeB.name) {
|
|
203
|
+
return "Equal" /* NodeComparisonResult.Equal */;
|
|
204
|
+
}
|
|
205
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
206
|
+
case utils_1.AST_NODE_TYPES.Literal: {
|
|
207
|
+
const nodeBLiteral = nodeB;
|
|
208
|
+
if (nodeA.raw === nodeBLiteral.raw &&
|
|
209
|
+
nodeA.value === nodeBLiteral.value) {
|
|
210
|
+
return "Equal" /* NodeComparisonResult.Equal */;
|
|
211
|
+
}
|
|
212
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
213
|
+
}
|
|
214
|
+
case utils_1.AST_NODE_TYPES.MemberExpression: {
|
|
215
|
+
const nodeBMember = nodeB;
|
|
216
|
+
if (nodeBMember.property.type === utils_1.AST_NODE_TYPES.PrivateIdentifier) {
|
|
217
|
+
// Private identifiers in optional chaining is not currently allowed
|
|
218
|
+
// TODO - handle this once TS supports it (https://github.com/microsoft/TypeScript/issues/42734)
|
|
219
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
220
|
+
}
|
|
221
|
+
// check for cases like
|
|
222
|
+
// foo.bar && foo.bar.baz
|
|
223
|
+
// ^^^^^^^ nodeA
|
|
224
|
+
// ^^^^^^^^^^^ nodeB
|
|
225
|
+
// result === Equal
|
|
226
|
+
//
|
|
227
|
+
// foo.bar && foo.bar.baz.bam
|
|
228
|
+
// ^^^^^^^ nodeA
|
|
229
|
+
// ^^^^^^^^^^^^^^^ nodeB
|
|
230
|
+
// result === Subset
|
|
231
|
+
//
|
|
232
|
+
// we don't want to check the property in this case
|
|
233
|
+
const aSubsetOfB = compareNodes(nodeA, nodeBMember.object);
|
|
234
|
+
if (aSubsetOfB !== "Invalid" /* NodeComparisonResult.Invalid */) {
|
|
235
|
+
return "Subset" /* NodeComparisonResult.Subset */;
|
|
236
|
+
}
|
|
237
|
+
if (nodeA.computed !== nodeBMember.computed) {
|
|
238
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
239
|
+
}
|
|
240
|
+
// NOTE - we purposely ignore optional flag because for our purposes
|
|
241
|
+
// foo?.bar && foo.bar?.baz
|
|
242
|
+
// or
|
|
243
|
+
// foo.bar && foo?.bar?.baz
|
|
244
|
+
// are going to be exactly the same
|
|
245
|
+
const objectCompare = compareNodes(nodeA.object, nodeBMember.object);
|
|
246
|
+
if (objectCompare !== "Equal" /* NodeComparisonResult.Equal */) {
|
|
247
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
248
|
+
}
|
|
249
|
+
return compareNodes(nodeA.property, nodeBMember.property);
|
|
250
|
+
}
|
|
251
|
+
case utils_1.AST_NODE_TYPES.TSTemplateLiteralType:
|
|
252
|
+
case utils_1.AST_NODE_TYPES.TemplateLiteral: {
|
|
253
|
+
const nodeBTemplate = nodeB;
|
|
254
|
+
const areQuasisEqual = nodeA.quasis.length === nodeBTemplate.quasis.length &&
|
|
255
|
+
nodeA.quasis.every((elA, idx) => {
|
|
256
|
+
const elB = nodeBTemplate.quasis[idx];
|
|
257
|
+
return elA.value.cooked === elB.value.cooked;
|
|
258
|
+
});
|
|
259
|
+
if (!areQuasisEqual) {
|
|
260
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
261
|
+
}
|
|
262
|
+
return "Equal" /* NodeComparisonResult.Equal */;
|
|
263
|
+
}
|
|
264
|
+
case utils_1.AST_NODE_TYPES.TemplateElement: {
|
|
265
|
+
const nodeBElement = nodeB;
|
|
266
|
+
if (nodeA.value.cooked === nodeBElement.value.cooked) {
|
|
267
|
+
return "Equal" /* NodeComparisonResult.Equal */;
|
|
268
|
+
}
|
|
269
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
270
|
+
}
|
|
271
|
+
// these aren't actually valid expressions.
|
|
272
|
+
// https://github.com/typescript-eslint/typescript-eslint/blob/20d7caee35ab84ae6381fdf04338c9e2b9e2bc48/packages/ast-spec/src/unions/Expression.ts#L37-L43
|
|
273
|
+
case utils_1.AST_NODE_TYPES.ArrayPattern:
|
|
274
|
+
case utils_1.AST_NODE_TYPES.ObjectPattern:
|
|
275
|
+
/* istanbul ignore next */
|
|
276
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
277
|
+
// update expression returns a number and also changes the value each time - so it makes no sense to compare the chain
|
|
278
|
+
case utils_1.AST_NODE_TYPES.UpdateExpression:
|
|
279
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
280
|
+
// yield returns the value passed to the `next` function, so it may not be the same each time - so it makes no sense to compare the chain
|
|
281
|
+
case utils_1.AST_NODE_TYPES.YieldExpression:
|
|
282
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
283
|
+
// general-case automatic handling of nodes to save us implementing every
|
|
284
|
+
// single case by hand. This just iterates the visitor keys to recursively
|
|
285
|
+
// check the children.
|
|
286
|
+
//
|
|
287
|
+
// Any specific logic cases or short-circuits should be listed as separate
|
|
288
|
+
// cases so that they don't fall into this generic handling
|
|
289
|
+
default:
|
|
290
|
+
return compareByVisiting(nodeA, nodeB);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
const COMPARE_NODES_CACHE = new WeakMap();
|
|
294
|
+
/**
|
|
295
|
+
* Compares two nodes' ASTs to determine if the A is equal to or a subset of B
|
|
296
|
+
*/
|
|
297
|
+
function compareNodes(nodeA, nodeB) {
|
|
298
|
+
if (nodeA == null || nodeB == null) {
|
|
299
|
+
if (nodeA !== nodeB) {
|
|
300
|
+
return "Invalid" /* NodeComparisonResult.Invalid */;
|
|
301
|
+
}
|
|
302
|
+
return "Equal" /* NodeComparisonResult.Equal */;
|
|
303
|
+
}
|
|
304
|
+
const cached = COMPARE_NODES_CACHE.get(nodeA)?.get(nodeB);
|
|
305
|
+
if (cached) {
|
|
306
|
+
return cached;
|
|
307
|
+
}
|
|
308
|
+
const result = compareNodesUncached(nodeA, nodeB);
|
|
309
|
+
let mapA = COMPARE_NODES_CACHE.get(nodeA);
|
|
310
|
+
if (mapA == null) {
|
|
311
|
+
mapA = new WeakMap();
|
|
312
|
+
COMPARE_NODES_CACHE.set(nodeA, mapA);
|
|
313
|
+
}
|
|
314
|
+
mapA.set(nodeB, result);
|
|
315
|
+
return result;
|
|
316
|
+
}
|
|
317
|
+
exports.compareNodes = compareNodes;
|
|
318
|
+
//# sourceMappingURL=compareNodes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compareNodes.js","sourceRoot":"","sources":["../../../src/rules/prefer-optional-chain-utils/compareNodes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.gatherLogicalOperands = void 0;
|
|
27
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
28
|
+
const ts_api_utils_1 = require("ts-api-utils");
|
|
29
|
+
const ts = __importStar(require("typescript"));
|
|
30
|
+
const util = __importStar(require("../../util"));
|
|
31
|
+
const NULLISH_FLAGS = ts.TypeFlags.Null | ts.TypeFlags.Undefined;
|
|
32
|
+
function isValidFalseBooleanCheckType(node, operator, checkType, parserServices, options) {
|
|
33
|
+
const type = parserServices.getTypeAtLocation(node);
|
|
34
|
+
const types = (0, ts_api_utils_1.unionTypeParts)(type);
|
|
35
|
+
const disallowFalseyLiteral = (operator === '||' && checkType === 'false') ||
|
|
36
|
+
(operator === '&&' && checkType === 'true');
|
|
37
|
+
if (disallowFalseyLiteral) {
|
|
38
|
+
/*
|
|
39
|
+
```
|
|
40
|
+
declare const x: false | {a: string};
|
|
41
|
+
x && x.a;
|
|
42
|
+
!x || x.a;
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
We don't want to consider these two cases because the boolean expression
|
|
46
|
+
narrows out the non-nullish falsy cases - so converting the chain to `x?.a`
|
|
47
|
+
would introduce a build error
|
|
48
|
+
*/
|
|
49
|
+
if (types.some(t => (0, ts_api_utils_1.isBooleanLiteralType)(t) && t.intrinsicName === 'false') ||
|
|
50
|
+
types.some(t => (0, ts_api_utils_1.isStringLiteralType)(t) && t.value === '') ||
|
|
51
|
+
types.some(t => (0, ts_api_utils_1.isNumberLiteralType)(t) && t.value === 0) ||
|
|
52
|
+
types.some(t => (0, ts_api_utils_1.isBigIntLiteralType)(t) && t.value.base10Value === '0')) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (options.requireNullish === true) {
|
|
57
|
+
return types.some(t => util.isTypeFlagSet(t, NULLISH_FLAGS));
|
|
58
|
+
}
|
|
59
|
+
let allowedFlags = NULLISH_FLAGS | ts.TypeFlags.Object;
|
|
60
|
+
if (options.checkAny === true) {
|
|
61
|
+
allowedFlags |= ts.TypeFlags.Any;
|
|
62
|
+
}
|
|
63
|
+
if (options.checkUnknown === true) {
|
|
64
|
+
allowedFlags |= ts.TypeFlags.Unknown;
|
|
65
|
+
}
|
|
66
|
+
if (options.checkString === true) {
|
|
67
|
+
allowedFlags |= ts.TypeFlags.StringLike;
|
|
68
|
+
}
|
|
69
|
+
if (options.checkNumber === true) {
|
|
70
|
+
allowedFlags |= ts.TypeFlags.NumberLike;
|
|
71
|
+
}
|
|
72
|
+
if (options.checkBoolean === true) {
|
|
73
|
+
allowedFlags |= ts.TypeFlags.BooleanLike;
|
|
74
|
+
}
|
|
75
|
+
if (options.checkBigInt === true) {
|
|
76
|
+
allowedFlags |= ts.TypeFlags.BigIntLike;
|
|
77
|
+
}
|
|
78
|
+
return types.every(t => util.isTypeFlagSet(t, allowedFlags));
|
|
79
|
+
}
|
|
80
|
+
function gatherLogicalOperands(node, parserServices, options) {
|
|
81
|
+
const result = [];
|
|
82
|
+
const { operands, newlySeenLogicals } = flattenLogicalOperands(node);
|
|
83
|
+
for (const operand of operands) {
|
|
84
|
+
switch (operand.type) {
|
|
85
|
+
case utils_1.AST_NODE_TYPES.BinaryExpression: {
|
|
86
|
+
// check for "yoda" style logical: null != x
|
|
87
|
+
const { comparedExpression, comparedValue, isYoda } = (() => {
|
|
88
|
+
// non-yoda checks are by far the most common, so check for them first
|
|
89
|
+
const comparedValueRight = getComparisonValueType(operand.right);
|
|
90
|
+
if (comparedValueRight) {
|
|
91
|
+
return {
|
|
92
|
+
comparedExpression: operand.left,
|
|
93
|
+
comparedValue: comparedValueRight,
|
|
94
|
+
isYoda: false,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
return {
|
|
99
|
+
comparedExpression: operand.right,
|
|
100
|
+
comparedValue: getComparisonValueType(operand.left),
|
|
101
|
+
isYoda: true,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
})();
|
|
105
|
+
if (comparedValue === "UndefinedStringLiteral" /* ComparisonValueType.UndefinedStringLiteral */) {
|
|
106
|
+
if (comparedExpression.type === utils_1.AST_NODE_TYPES.UnaryExpression &&
|
|
107
|
+
comparedExpression.operator === 'typeof') {
|
|
108
|
+
// typeof x === 'undefined'
|
|
109
|
+
result.push({
|
|
110
|
+
type: "Valid" /* OperandValidity.Valid */,
|
|
111
|
+
comparedName: comparedExpression.argument,
|
|
112
|
+
comparisonType: operand.operator.startsWith('!')
|
|
113
|
+
? "NotStrictEqualUndefined" /* NullishComparisonType.NotStrictEqualUndefined */
|
|
114
|
+
: "StrictEqualUndefined" /* NullishComparisonType.StrictEqualUndefined */,
|
|
115
|
+
isYoda,
|
|
116
|
+
node: operand,
|
|
117
|
+
});
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
// y === 'undefined'
|
|
121
|
+
result.push({ type: "Invalid" /* OperandValidity.Invalid */ });
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
switch (operand.operator) {
|
|
125
|
+
case '!=':
|
|
126
|
+
case '==':
|
|
127
|
+
if (comparedValue === "Null" /* ComparisonValueType.Null */ ||
|
|
128
|
+
comparedValue === "Undefined" /* ComparisonValueType.Undefined */) {
|
|
129
|
+
// x == null, x == undefined
|
|
130
|
+
result.push({
|
|
131
|
+
type: "Valid" /* OperandValidity.Valid */,
|
|
132
|
+
comparedName: comparedExpression,
|
|
133
|
+
comparisonType: operand.operator.startsWith('!')
|
|
134
|
+
? "NotEqualNullOrUndefined" /* NullishComparisonType.NotEqualNullOrUndefined */
|
|
135
|
+
: "EqualNullOrUndefined" /* NullishComparisonType.EqualNullOrUndefined */,
|
|
136
|
+
isYoda,
|
|
137
|
+
node: operand,
|
|
138
|
+
});
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
// x == something :(
|
|
142
|
+
result.push({ type: "Invalid" /* OperandValidity.Invalid */ });
|
|
143
|
+
continue;
|
|
144
|
+
case '!==':
|
|
145
|
+
case '===': {
|
|
146
|
+
const comparedName = comparedExpression;
|
|
147
|
+
switch (comparedValue) {
|
|
148
|
+
case "Null" /* ComparisonValueType.Null */:
|
|
149
|
+
result.push({
|
|
150
|
+
type: "Valid" /* OperandValidity.Valid */,
|
|
151
|
+
comparedName,
|
|
152
|
+
comparisonType: operand.operator.startsWith('!')
|
|
153
|
+
? "NotStrictEqualNull" /* NullishComparisonType.NotStrictEqualNull */
|
|
154
|
+
: "StrictEqualNull" /* NullishComparisonType.StrictEqualNull */,
|
|
155
|
+
isYoda,
|
|
156
|
+
node: operand,
|
|
157
|
+
});
|
|
158
|
+
continue;
|
|
159
|
+
case "Undefined" /* ComparisonValueType.Undefined */:
|
|
160
|
+
result.push({
|
|
161
|
+
type: "Valid" /* OperandValidity.Valid */,
|
|
162
|
+
comparedName,
|
|
163
|
+
comparisonType: operand.operator.startsWith('!')
|
|
164
|
+
? "NotStrictEqualUndefined" /* NullishComparisonType.NotStrictEqualUndefined */
|
|
165
|
+
: "StrictEqualUndefined" /* NullishComparisonType.StrictEqualUndefined */,
|
|
166
|
+
isYoda,
|
|
167
|
+
node: operand,
|
|
168
|
+
});
|
|
169
|
+
continue;
|
|
170
|
+
default:
|
|
171
|
+
// x === something :(
|
|
172
|
+
result.push({ type: "Invalid" /* OperandValidity.Invalid */ });
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
result.push({ type: "Invalid" /* OperandValidity.Invalid */ });
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
case utils_1.AST_NODE_TYPES.UnaryExpression:
|
|
181
|
+
if (operand.operator === '!' &&
|
|
182
|
+
isValidFalseBooleanCheckType(operand.argument, node.operator, 'false', parserServices, options)) {
|
|
183
|
+
result.push({
|
|
184
|
+
type: "Valid" /* OperandValidity.Valid */,
|
|
185
|
+
comparedName: operand.argument,
|
|
186
|
+
comparisonType: "NotBoolean" /* NullishComparisonType.NotBoolean */,
|
|
187
|
+
isYoda: false,
|
|
188
|
+
node: operand,
|
|
189
|
+
});
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
result.push({ type: "Invalid" /* OperandValidity.Invalid */ });
|
|
193
|
+
continue;
|
|
194
|
+
case utils_1.AST_NODE_TYPES.LogicalExpression:
|
|
195
|
+
// explicitly ignore the mixed logical expression cases
|
|
196
|
+
result.push({ type: "Invalid" /* OperandValidity.Invalid */ });
|
|
197
|
+
continue;
|
|
198
|
+
default:
|
|
199
|
+
if (isValidFalseBooleanCheckType(operand, node.operator, 'true', parserServices, options)) {
|
|
200
|
+
result.push({
|
|
201
|
+
type: "Valid" /* OperandValidity.Valid */,
|
|
202
|
+
comparedName: operand,
|
|
203
|
+
comparisonType: "Boolean" /* NullishComparisonType.Boolean */,
|
|
204
|
+
isYoda: false,
|
|
205
|
+
node: operand,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
result.push({ type: "Invalid" /* OperandValidity.Invalid */ });
|
|
210
|
+
}
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
operands: result,
|
|
216
|
+
newlySeenLogicals,
|
|
217
|
+
};
|
|
218
|
+
/*
|
|
219
|
+
The AST is always constructed such the first element is always the deepest element.
|
|
220
|
+
I.e. for this code: `foo && foo.bar && foo.bar.baz && foo.bar.baz.buzz`
|
|
221
|
+
The AST will look like this:
|
|
222
|
+
{
|
|
223
|
+
left: {
|
|
224
|
+
left: {
|
|
225
|
+
left: foo
|
|
226
|
+
right: foo.bar
|
|
227
|
+
}
|
|
228
|
+
right: foo.bar.baz
|
|
229
|
+
}
|
|
230
|
+
right: foo.bar.baz.buzz
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
So given any logical expression, we can perform a depth-first traversal to get
|
|
234
|
+
the operands in order.
|
|
235
|
+
|
|
236
|
+
Note that this function purposely does not inspect mixed logical expressions
|
|
237
|
+
like `foo || foo.bar && foo.bar.baz` - separate selector
|
|
238
|
+
*/
|
|
239
|
+
function flattenLogicalOperands(node) {
|
|
240
|
+
const operands = [];
|
|
241
|
+
const newlySeenLogicals = new Set([node]);
|
|
242
|
+
const stack = [node.right, node.left];
|
|
243
|
+
let current;
|
|
244
|
+
while ((current = stack.pop())) {
|
|
245
|
+
if (current.type === utils_1.AST_NODE_TYPES.LogicalExpression &&
|
|
246
|
+
current.operator === node.operator) {
|
|
247
|
+
newlySeenLogicals.add(current);
|
|
248
|
+
stack.push(current.right);
|
|
249
|
+
stack.push(current.left);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
operands.push(current);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
operands,
|
|
257
|
+
newlySeenLogicals,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function getComparisonValueType(node) {
|
|
261
|
+
switch (node.type) {
|
|
262
|
+
case utils_1.AST_NODE_TYPES.Literal:
|
|
263
|
+
// eslint-disable-next-line eqeqeq -- intentional exact comparison against null
|
|
264
|
+
if (node.value === null && node.raw === 'null') {
|
|
265
|
+
return "Null" /* ComparisonValueType.Null */;
|
|
266
|
+
}
|
|
267
|
+
if (node.value === 'undefined') {
|
|
268
|
+
return "UndefinedStringLiteral" /* ComparisonValueType.UndefinedStringLiteral */;
|
|
269
|
+
}
|
|
270
|
+
return null;
|
|
271
|
+
case utils_1.AST_NODE_TYPES.Identifier:
|
|
272
|
+
if (node.name === 'undefined') {
|
|
273
|
+
return "Undefined" /* ComparisonValueType.Undefined */;
|
|
274
|
+
}
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
exports.gatherLogicalOperands = gatherLogicalOperands;
|
|
281
|
+
//# sourceMappingURL=gatherLogicalOperands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gatherLogicalOperands.js","sourceRoot":"","sources":["../../../src/rules/prefer-optional-chain-utils/gatherLogicalOperands.ts"],"names":[],"mappings":"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"}
|