@typescript-eslint/eslint-plugin 8.61.1-alpha.3 → 8.61.1-alpha.4
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/dist/rules/no-unnecessary-boolean-literal-compare.js +39 -26
- package/dist/rules/no-unnecessary-template-expression.js +1 -1
- package/dist/rules/no-unnecessary-type-assertion.js +21 -2
- package/dist/util/getWrappingFixer.d.ts +4 -0
- package/dist/util/getWrappingFixer.js +1 -0
- package/package.json +8 -8
|
@@ -163,11 +163,11 @@ exports.default = (0, util_1.createRule)({
|
|
|
163
163
|
typeof against.value !== 'boolean') {
|
|
164
164
|
continue;
|
|
165
165
|
}
|
|
166
|
-
const
|
|
166
|
+
const booleanLiteral = against.value ? 'true' : 'false';
|
|
167
167
|
const negated = !comparisonType.isPositive;
|
|
168
168
|
return {
|
|
169
|
+
booleanLiteral,
|
|
169
170
|
expression,
|
|
170
|
-
literalBooleanInComparison,
|
|
171
171
|
negated,
|
|
172
172
|
};
|
|
173
173
|
}
|
|
@@ -183,11 +183,11 @@ exports.default = (0, util_1.createRule)({
|
|
|
183
183
|
return;
|
|
184
184
|
}
|
|
185
185
|
if (comparison.expressionIsNullableBoolean) {
|
|
186
|
-
if (comparison.
|
|
186
|
+
if (comparison.booleanLiteral === 'true' &&
|
|
187
187
|
options.allowComparingNullableBooleansToTrue) {
|
|
188
188
|
return;
|
|
189
189
|
}
|
|
190
|
-
if (
|
|
190
|
+
if (comparison.booleanLiteral === 'false' &&
|
|
191
191
|
options.allowComparingNullableBooleansToFalse) {
|
|
192
192
|
return;
|
|
193
193
|
}
|
|
@@ -195,7 +195,7 @@ exports.default = (0, util_1.createRule)({
|
|
|
195
195
|
context.report({
|
|
196
196
|
node,
|
|
197
197
|
messageId: comparison.expressionIsNullableBoolean
|
|
198
|
-
? comparison.
|
|
198
|
+
? comparison.booleanLiteral === 'true'
|
|
199
199
|
? comparison.negated
|
|
200
200
|
? 'comparingNullableToTrueNegated'
|
|
201
201
|
: 'comparingNullableToTrueDirect'
|
|
@@ -203,30 +203,36 @@ exports.default = (0, util_1.createRule)({
|
|
|
203
203
|
: comparison.negated
|
|
204
204
|
? 'negated'
|
|
205
205
|
: 'direct',
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
//
|
|
210
|
-
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
206
|
+
fix(fixer) {
|
|
207
|
+
const isWrappedInUnaryNegation = nodeIsUnaryNegation(node.parent);
|
|
208
|
+
const mutatedNode = isWrappedInUnaryNegation ? node.parent : node;
|
|
209
|
+
// Whether the truth table of the overall expression being replaced
|
|
210
|
+
// is negated, _ignoring the nullish cases_.
|
|
211
|
+
const isOverallNegated = booleanXor(isWrappedInUnaryNegation, comparison.negated, comparison.booleanLiteral === 'false');
|
|
212
|
+
// we'll build up the replacement text from the compared expression outwards.
|
|
213
|
+
let replacementText = context.sourceCode.getText(comparison.expression);
|
|
214
|
+
let mayNeedParentheses = !(0, util_1.isStrongPrecedenceNode)(comparison.expression);
|
|
215
|
+
// In maybeNullish === false, nullish values have the same truth table
|
|
216
|
+
// as `true`.
|
|
217
|
+
if (comparison.expressionIsNullableBoolean &&
|
|
218
|
+
comparison.booleanLiteral === 'false') {
|
|
219
|
+
if (mayNeedParentheses) {
|
|
220
|
+
replacementText = parenthesize(replacementText);
|
|
221
221
|
}
|
|
222
|
+
replacementText = `${replacementText} ?? true`;
|
|
223
|
+
mayNeedParentheses = true;
|
|
222
224
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
225
|
+
if (isOverallNegated) {
|
|
226
|
+
if (mayNeedParentheses) {
|
|
227
|
+
replacementText = parenthesize(replacementText);
|
|
228
|
+
}
|
|
229
|
+
replacementText = `!${replacementText}`;
|
|
230
|
+
mayNeedParentheses = false;
|
|
229
231
|
}
|
|
232
|
+
if (mayNeedParentheses && (0, util_1.isWeakPrecedenceParent)(mutatedNode)) {
|
|
233
|
+
replacementText = parenthesize(replacementText);
|
|
234
|
+
}
|
|
235
|
+
return fixer.replaceText(mutatedNode, replacementText);
|
|
230
236
|
},
|
|
231
237
|
});
|
|
232
238
|
},
|
|
@@ -259,3 +265,10 @@ function getEqualsKind(operator) {
|
|
|
259
265
|
return undefined;
|
|
260
266
|
}
|
|
261
267
|
}
|
|
268
|
+
function booleanXor(arg0, ...args) {
|
|
269
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion
|
|
270
|
+
return args.reduce((acc, curr) => acc !== Boolean(curr), Boolean(arg0));
|
|
271
|
+
}
|
|
272
|
+
function parenthesize(text) {
|
|
273
|
+
return `(${text})`;
|
|
274
|
+
}
|
|
@@ -565,10 +565,29 @@ exports.default = (0, util_1.createRule)({
|
|
|
565
565
|
token.value === '<'), util_1.NullThrowsReasons.MissingToken('<', 'type annotation'));
|
|
566
566
|
const closingAngleBracket = (0, util_1.nullThrows)(context.sourceCode.getTokenAfter(node.typeAnnotation, token => token.type === utils_1.AST_TOKEN_TYPES.Punctuator &&
|
|
567
567
|
token.value === '>'), util_1.NullThrowsReasons.MissingToken('>', 'type annotation'));
|
|
568
|
-
|
|
568
|
+
// Removing the angle-bracketed type can leave a bare object
|
|
569
|
+
// literal in a position where `{` is parsed as a block (concise
|
|
570
|
+
// arrow body, or the start of an expression statement). Wrap the
|
|
571
|
+
// result in parentheses to preserve the original expression
|
|
572
|
+
// semantics.
|
|
573
|
+
const needsParens = node.expression.type === utils_1.AST_NODE_TYPES.ObjectExpression &&
|
|
574
|
+
((node.parent.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression &&
|
|
575
|
+
node.parent.body === node) ||
|
|
576
|
+
node.parent.type === utils_1.AST_NODE_TYPES.ExpressionStatement) &&
|
|
577
|
+
!(0, util_1.isParenthesized)(node, context.sourceCode) &&
|
|
578
|
+
!(0, util_1.isParenthesized)(node.expression, context.sourceCode);
|
|
579
|
+
const fixes = [];
|
|
580
|
+
if (needsParens) {
|
|
581
|
+
fixes.push(fixer.insertTextBefore(node, '('));
|
|
582
|
+
}
|
|
583
|
+
fixes.push(fixer.removeRange([
|
|
569
584
|
openingAngleBracket.range[0],
|
|
570
585
|
closingAngleBracket.range[1],
|
|
571
|
-
]);
|
|
586
|
+
]));
|
|
587
|
+
if (needsParens) {
|
|
588
|
+
fixes.push(fixer.insertTextAfter(node, ')'));
|
|
589
|
+
}
|
|
590
|
+
return fixes;
|
|
572
591
|
}
|
|
573
592
|
const asToken = (0, util_1.nullThrows)(context.sourceCode.getTokenAfter(node.expression, token => token.type === utils_1.AST_TOKEN_TYPES.Identifier && token.value === 'as'), util_1.NullThrowsReasons.MissingToken('>', 'type annotation'));
|
|
574
593
|
const tokenBeforeAs = (0, util_1.nullThrows)(context.sourceCode.getTokenBefore(asToken, {
|
|
@@ -39,4 +39,8 @@ export declare function getMovedNodeCode(params: {
|
|
|
39
39
|
* Check if a node will always have the same precedence if its parent changes.
|
|
40
40
|
*/
|
|
41
41
|
export declare function isStrongPrecedenceNode(innerNode: TSESTree.Node): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Check if a node's parent could have different precedence if the node changes.
|
|
44
|
+
*/
|
|
45
|
+
export declare function isWeakPrecedenceParent(node: TSESTree.Node): boolean;
|
|
42
46
|
export {};
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getWrappingFixer = getWrappingFixer;
|
|
4
4
|
exports.getMovedNodeCode = getMovedNodeCode;
|
|
5
5
|
exports.isStrongPrecedenceNode = isStrongPrecedenceNode;
|
|
6
|
+
exports.isWeakPrecedenceParent = isWeakPrecedenceParent;
|
|
6
7
|
const utils_1 = require("@typescript-eslint/utils");
|
|
7
8
|
/**
|
|
8
9
|
* Wraps node with some code. Adds parentheses as necessary.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typescript-eslint/eslint-plugin",
|
|
3
|
-
"version": "8.61.1-alpha.
|
|
3
|
+
"version": "8.61.1-alpha.4",
|
|
4
4
|
"description": "TypeScript plugin for ESLint",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -52,10 +52,10 @@
|
|
|
52
52
|
"ignore": "^7.0.5",
|
|
53
53
|
"natural-compare": "^1.4.0",
|
|
54
54
|
"ts-api-utils": "^2.5.0",
|
|
55
|
-
"@typescript-eslint/
|
|
56
|
-
"@typescript-eslint/
|
|
57
|
-
"@typescript-eslint/
|
|
58
|
-
"@typescript-eslint/
|
|
55
|
+
"@typescript-eslint/scope-manager": "8.61.1-alpha.4",
|
|
56
|
+
"@typescript-eslint/type-utils": "8.61.1-alpha.4",
|
|
57
|
+
"@typescript-eslint/utils": "8.61.1-alpha.4",
|
|
58
|
+
"@typescript-eslint/visitor-keys": "8.61.1-alpha.4"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@types/json-schema": "^7.0.15",
|
|
@@ -79,13 +79,13 @@
|
|
|
79
79
|
"typescript": ">=4.8.4 <6.1.0",
|
|
80
80
|
"unist-util-visit": "^5.0.0",
|
|
81
81
|
"vitest": "^4.0.18",
|
|
82
|
-
"@typescript-eslint/rule-schema-to-typescript-types": "8.61.1-alpha.
|
|
83
|
-
"@typescript-eslint/rule-tester": "8.61.1-alpha.
|
|
82
|
+
"@typescript-eslint/rule-schema-to-typescript-types": "8.61.1-alpha.4",
|
|
83
|
+
"@typescript-eslint/rule-tester": "8.61.1-alpha.4"
|
|
84
84
|
},
|
|
85
85
|
"peerDependencies": {
|
|
86
86
|
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
|
|
87
87
|
"typescript": ">=4.8.4 <6.1.0",
|
|
88
|
-
"@typescript-eslint/parser": "^8.61.1-alpha.
|
|
88
|
+
"@typescript-eslint/parser": "^8.61.1-alpha.4"
|
|
89
89
|
},
|
|
90
90
|
"funding": {
|
|
91
91
|
"type": "opencollective",
|