oxlint-plugin-eslint 1.52.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/LICENSE +22 -0
- package/README.md +36 -0
- package/common/ast-utils.cjs +5843 -0
- package/common/chunk.cjs +9 -0
- package/common/eslint-utils.cjs +1633 -0
- package/common/fix-tracker.cjs +89 -0
- package/common/ignore.cjs +123 -0
- package/common/keywords.cjs +15 -0
- package/common/regexpp.cjs +1720 -0
- package/common/regular-expressions.cjs +40 -0
- package/common/string-utils.cjs +39 -0
- package/index.js +7477 -0
- package/package.json +34 -0
- package/rules/accessor-pairs.cjs +233 -0
- package/rules/array-bracket-newline.cjs +172 -0
- package/rules/array-bracket-spacing.cjs +184 -0
- package/rules/array-callback-return.cjs +262 -0
- package/rules/array-element-newline.cjs +178 -0
- package/rules/arrow-body-style.cjs +135 -0
- package/rules/arrow-parens.cjs +130 -0
- package/rules/arrow-spacing.cjs +129 -0
- package/rules/block-scoped-var.cjs +101 -0
- package/rules/block-spacing.cjs +125 -0
- package/rules/brace-style.cjs +141 -0
- package/rules/callback-return.cjs +117 -0
- package/rules/camelcase.cjs +194 -0
- package/rules/capitalized-comments.cjs +168 -0
- package/rules/class-methods-use-this.cjs +155 -0
- package/rules/comma-dangle.cjs +274 -0
- package/rules/comma-spacing.cjs +111 -0
- package/rules/comma-style.cjs +180 -0
- package/rules/complexity.cjs +100 -0
- package/rules/computed-property-spacing.cjs +155 -0
- package/rules/consistent-return.cjs +113 -0
- package/rules/consistent-this.cjs +109 -0
- package/rules/constructor-super.cjs +207 -0
- package/rules/curly.cjs +173 -0
- package/rules/default-case-last.cjs +36 -0
- package/rules/default-case.cjs +50 -0
- package/rules/default-param-last.cjs +61 -0
- package/rules/dot-location.cjs +87 -0
- package/rules/dot-notation.cjs +77 -0
- package/rules/eol-last.cjs +91 -0
- package/rules/eqeqeq.cjs +127 -0
- package/rules/for-direction.cjs +94 -0
- package/rules/func-call-spacing.cjs +127 -0
- package/rules/func-name-matching.cjs +138 -0
- package/rules/func-names.cjs +121 -0
- package/rules/func-style.cjs +103 -0
- package/rules/function-call-argument-newline.cjs +109 -0
- package/rules/function-paren-newline.cjs +173 -0
- package/rules/generator-star-spacing.cjs +174 -0
- package/rules/getter-return.cjs +129 -0
- package/rules/global-require.cjs +84 -0
- package/rules/grouped-accessor-pairs.cjs +146 -0
- package/rules/guard-for-in.cjs +39 -0
- package/rules/handle-callback-err.cjs +86 -0
- package/rules/id-blacklist.cjs +135 -0
- package/rules/id-denylist.cjs +126 -0
- package/rules/id-length.cjs +119 -0
- package/rules/id-match.cjs +139 -0
- package/rules/implicit-arrow-linebreak.cjs +76 -0
- package/rules/indent-legacy.cjs +520 -0
- package/rules/indent.cjs +842 -0
- package/rules/init-declarations.cjs +88 -0
- package/rules/jsx-quotes.cjs +84 -0
- package/rules/key-spacing.cjs +399 -0
- package/rules/keyword-spacing.cjs +464 -0
- package/rules/line-comment-position.cjs +75 -0
- package/rules/linebreak-style.cjs +89 -0
- package/rules/lines-around-comment.cjs +290 -0
- package/rules/lines-around-directive.cjs +129 -0
- package/rules/lines-between-class-members.cjs +212 -0
- package/rules/logical-assignment-operators.cjs +305 -0
- package/rules/max-classes-per-file.cjs +61 -0
- package/rules/max-depth.cjs +117 -0
- package/rules/max-len.cjs +256 -0
- package/rules/max-lines-per-function.cjs +116 -0
- package/rules/max-lines.cjs +109 -0
- package/rules/max-nested-callbacks.cjs +78 -0
- package/rules/max-params.cjs +78 -0
- package/rules/max-statements-per-line.cjs +147 -0
- package/rules/max-statements.cjs +119 -0
- package/rules/multiline-comment-style.cjs +319 -0
- package/rules/multiline-ternary.cjs +106 -0
- package/rules/new-cap.cjs +139 -0
- package/rules/new-parens.cjs +70 -0
- package/rules/newline-after-var.cjs +159 -0
- package/rules/newline-before-return.cjs +128 -0
- package/rules/newline-per-chained-call.cjs +100 -0
- package/rules/no-alert.cjs +84 -0
- package/rules/no-array-constructor.cjs +91 -0
- package/rules/no-async-promise-executor.cjs +33 -0
- package/rules/no-await-in-loop.cjs +75 -0
- package/rules/no-bitwise.cjs +106 -0
- package/rules/no-buffer-constructor.cjs +51 -0
- package/rules/no-caller.cjs +34 -0
- package/rules/no-case-declarations.cjs +56 -0
- package/rules/no-catch-shadow.cjs +57 -0
- package/rules/no-class-assign.cjs +55 -0
- package/rules/no-compare-neg-zero.cjs +52 -0
- package/rules/no-cond-assign.cjs +104 -0
- package/rules/no-confusing-arrow.cjs +87 -0
- package/rules/no-console.cjs +138 -0
- package/rules/no-const-assign.cjs +50 -0
- package/rules/no-constant-binary-expression.cjs +284 -0
- package/rules/no-constant-condition.cjs +119 -0
- package/rules/no-constructor-return.cjs +43 -0
- package/rules/no-continue.cjs +33 -0
- package/rules/no-control-regex.cjs +74 -0
- package/rules/no-debugger.cjs +33 -0
- package/rules/no-delete-var.cjs +32 -0
- package/rules/no-div-regex.cjs +39 -0
- package/rules/no-dupe-args.cjs +61 -0
- package/rules/no-dupe-class-members.cjs +77 -0
- package/rules/no-dupe-else-if.cjs +74 -0
- package/rules/no-dupe-keys.cjs +88 -0
- package/rules/no-duplicate-case.cjs +49 -0
- package/rules/no-duplicate-imports.cjs +166 -0
- package/rules/no-else-return.cjs +182 -0
- package/rules/no-empty-character-class.cjs +47 -0
- package/rules/no-empty-function.cjs +141 -0
- package/rules/no-empty-pattern.cjs +50 -0
- package/rules/no-empty-static-block.cjs +50 -0
- package/rules/no-empty.cjs +78 -0
- package/rules/no-eq-null.cjs +34 -0
- package/rules/no-eval.cjs +165 -0
- package/rules/no-ex-assign.cjs +45 -0
- package/rules/no-extend-native.cjs +103 -0
- package/rules/no-extra-bind.cjs +127 -0
- package/rules/no-extra-boolean-cast.cjs +159 -0
- package/rules/no-extra-label.cjs +116 -0
- package/rules/no-extra-parens.cjs +665 -0
- package/rules/no-extra-semi.cjs +103 -0
- package/rules/no-fallthrough.cjs +136 -0
- package/rules/no-floating-decimal.cjs +66 -0
- package/rules/no-func-assign.cjs +63 -0
- package/rules/no-global-assign.cjs +62 -0
- package/rules/no-implicit-coercion.cjs +219 -0
- package/rules/no-implicit-globals.cjs +77 -0
- package/rules/no-implied-eval.cjs +87 -0
- package/rules/no-import-assign.cjs +123 -0
- package/rules/no-inline-comments.cjs +57 -0
- package/rules/no-inner-declarations.cjs +82 -0
- package/rules/no-invalid-regexp.cjs +130 -0
- package/rules/no-invalid-this.cjs +90 -0
- package/rules/no-irregular-whitespace.cjs +157 -0
- package/rules/no-iterator.cjs +34 -0
- package/rules/no-label-var.cjs +46 -0
- package/rules/no-labels.cjs +106 -0
- package/rules/no-lone-blocks.cjs +75 -0
- package/rules/no-lonely-if.cjs +42 -0
- package/rules/no-loop-func.cjs +143 -0
- package/rules/no-loss-of-precision.cjs +160 -0
- package/rules/no-magic-numbers.cjs +222 -0
- package/rules/no-misleading-character-class.cjs +500 -0
- package/rules/no-mixed-operators.cjs +197 -0
- package/rules/no-mixed-requires.cjs +117 -0
- package/rules/no-mixed-spaces-and-tabs.cjs +87 -0
- package/rules/no-multi-assign.cjs +38 -0
- package/rules/no-multi-spaces.cjs +95 -0
- package/rules/no-multi-str.cjs +44 -0
- package/rules/no-multiple-empty-lines.cjs +112 -0
- package/rules/no-native-reassign.cjs +72 -0
- package/rules/no-negated-condition.cjs +77 -0
- package/rules/no-negated-in-lhs.cjs +43 -0
- package/rules/no-nested-ternary.cjs +33 -0
- package/rules/no-new-func.cjs +50 -0
- package/rules/no-new-native-nonconstructor.cjs +42 -0
- package/rules/no-new-object.cjs +47 -0
- package/rules/no-new-require.cjs +50 -0
- package/rules/no-new-symbol.cjs +48 -0
- package/rules/no-new-wrappers.cjs +44 -0
- package/rules/no-new.cjs +33 -0
- package/rules/no-nonoctal-decimal-escape.cjs +80 -0
- package/rules/no-obj-calls.cjs +64 -0
- package/rules/no-object-constructor.cjs +69 -0
- package/rules/no-octal-escape.cjs +35 -0
- package/rules/no-octal.cjs +32 -0
- package/rules/no-param-reassign.cjs +135 -0
- package/rules/no-path-concat.cjs +52 -0
- package/rules/no-plusplus.cjs +64 -0
- package/rules/no-process-env.cjs +51 -0
- package/rules/no-process-exit.cjs +50 -0
- package/rules/no-promise-executor-return.cjs +131 -0
- package/rules/no-proto.cjs +34 -0
- package/rules/no-prototype-builtins.cjs +85 -0
- package/rules/no-redeclare.cjs +103 -0
- package/rules/no-regex-spaces.cjs +115 -0
- package/rules/no-restricted-exports.cjs +117 -0
- package/rules/no-restricted-globals.cjs +147 -0
- package/rules/no-restricted-imports.cjs +421 -0
- package/rules/no-restricted-modules.cjs +144 -0
- package/rules/no-restricted-properties.cjs +123 -0
- package/rules/no-restricted-syntax.cjs +49 -0
- package/rules/no-return-assign.cjs +45 -0
- package/rules/no-return-await.cjs +88 -0
- package/rules/no-script-url.cjs +49 -0
- package/rules/no-self-assign.cjs +88 -0
- package/rules/no-self-compare.cjs +53 -0
- package/rules/no-sequences.cjs +81 -0
- package/rules/no-setter-return.cjs +110 -0
- package/rules/no-shadow-restricted-names.cjs +60 -0
- package/rules/no-shadow.cjs +302 -0
- package/rules/no-spaced-func.cjs +69 -0
- package/rules/no-sparse-arrays.cjs +40 -0
- package/rules/no-sync.cjs +58 -0
- package/rules/no-tabs.cjs +73 -0
- package/rules/no-template-curly-in-string.cjs +33 -0
- package/rules/no-ternary.cjs +33 -0
- package/rules/no-this-before-super.cjs +177 -0
- package/rules/no-throw-literal.cjs +40 -0
- package/rules/no-trailing-spaces.cjs +123 -0
- package/rules/no-unassigned-vars.cjs +54 -0
- package/rules/no-undef-init.cjs +46 -0
- package/rules/no-undef.cjs +51 -0
- package/rules/no-undefined.cjs +58 -0
- package/rules/no-underscore-dangle.cjs +211 -0
- package/rules/no-unexpected-multiline.cjs +76 -0
- package/rules/no-unmodified-loop-condition.cjs +849 -0
- package/rules/no-unneeded-ternary.cjs +112 -0
- package/rules/no-unreachable-loop.cjs +128 -0
- package/rules/no-unreachable.cjs +195 -0
- package/rules/no-unsafe-finally.cjs +67 -0
- package/rules/no-unsafe-negation.cjs +86 -0
- package/rules/no-unsafe-optional-chaining.cjs +164 -0
- package/rules/no-unused-expressions.cjs +163 -0
- package/rules/no-unused-labels.cjs +97 -0
- package/rules/no-unused-private-class-members.cjs +69 -0
- package/rules/no-unused-vars.cjs +639 -0
- package/rules/no-use-before-define.cjs +245 -0
- package/rules/no-useless-assignment.cjs +250 -0
- package/rules/no-useless-backreference.cjs +137 -0
- package/rules/no-useless-call.cjs +57 -0
- package/rules/no-useless-catch.cjs +38 -0
- package/rules/no-useless-computed-key.cjs +106 -0
- package/rules/no-useless-concat.cjs +78 -0
- package/rules/no-useless-constructor.cjs +152 -0
- package/rules/no-useless-escape.cjs +164 -0
- package/rules/no-useless-rename.cjs +94 -0
- package/rules/no-useless-return.cjs +229 -0
- package/rules/no-var.cjs +235 -0
- package/rules/no-void.cjs +39 -0
- package/rules/no-warning-comments.cjs +112 -0
- package/rules/no-whitespace-before-property.cjs +72 -0
- package/rules/no-with.cjs +32 -0
- package/rules/nonblock-statement-body-position.cjs +107 -0
- package/rules/object-curly-newline.cjs +194 -0
- package/rules/object-curly-spacing.cjs +225 -0
- package/rules/object-property-newline.cjs +81 -0
- package/rules/object-shorthand.cjs +284 -0
- package/rules/one-var-declaration-per-line.cjs +75 -0
- package/rules/one-var.cjs +378 -0
- package/rules/operator-assignment.cjs +146 -0
- package/rules/operator-linebreak.cjs +150 -0
- package/rules/padded-blocks.cjs +192 -0
- package/rules/padding-line-between-statements.cjs +377 -0
- package/rules/prefer-arrow-callback.cjs +185 -0
- package/rules/prefer-const.cjs +240 -0
- package/rules/prefer-destructuring.cjs +188 -0
- package/rules/prefer-exponentiation-operator.cjs +100 -0
- package/rules/prefer-named-capture-group.cjs +111 -0
- package/rules/prefer-numeric-literals.cjs +75 -0
- package/rules/prefer-object-has-own.cjs +54 -0
- package/rules/prefer-object-spread.cjs +170 -0
- package/rules/prefer-promise-reject-errors.cjs +62 -0
- package/rules/prefer-reflect.cjs +100 -0
- package/rules/prefer-regex-literals.cjs +256 -0
- package/rules/prefer-rest-params.cjs +80 -0
- package/rules/prefer-spread.cjs +57 -0
- package/rules/prefer-template.cjs +147 -0
- package/rules/preserve-caught-error.cjs +196 -0
- package/rules/quote-props.cjs +224 -0
- package/rules/quotes.cjs +187 -0
- package/rules/radix.cjs +124 -0
- package/rules/require-atomic-updates.cjs +197 -0
- package/rules/require-await.cjs +90 -0
- package/rules/require-unicode-regexp.cjs +101 -0
- package/rules/require-yield.cjs +56 -0
- package/rules/rest-spread-spacing.cjs +99 -0
- package/rules/semi-spacing.cjs +215 -0
- package/rules/semi-style.cjs +116 -0
- package/rules/semi.cjs +239 -0
- package/rules/sort-imports.cjs +140 -0
- package/rules/sort-keys.cjs +165 -0
- package/rules/sort-vars.cjs +50 -0
- package/rules/space-before-blocks.cjs +132 -0
- package/rules/space-before-function-paren.cjs +126 -0
- package/rules/space-in-parens.cjs +175 -0
- package/rules/space-infix-ops.cjs +133 -0
- package/rules/space-unary-ops.cjs +237 -0
- package/rules/spaced-comment.cjs +233 -0
- package/rules/strict.cjs +206 -0
- package/rules/switch-colon-spacing.cjs +114 -0
- package/rules/symbol-description.cjs +49 -0
- package/rules/template-curly-spacing.cjs +112 -0
- package/rules/template-tag-spacing.cjs +82 -0
- package/rules/unicode-bom.cjs +52 -0
- package/rules/use-isnan.cjs +144 -0
- package/rules/valid-typeof.cjs +104 -0
- package/rules/vars-on-top.cjs +94 -0
- package/rules/wrap-iife.cjs +131 -0
- package/rules/wrap-regex.cjs +57 -0
- package/rules/yield-star-spacing.cjs +115 -0
- package/rules/yoda.cjs +185 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const require_chunk = require("../common/chunk.cjs"), require_ast_utils$1 = require("../common/ast-utils.cjs");
|
|
2
|
+
//#region ../../node_modules/.pnpm/eslint@9.39.3_jiti@2.6.1/node_modules/eslint/lib/rules/no-unneeded-ternary.js
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Rule to flag no-unneeded-ternary
|
|
5
|
+
* @author Gyandeep Singh
|
|
6
|
+
*/
|
|
7
|
+
var require_no_unneeded_ternary = /* @__PURE__ */ require_chunk.t(((exports, module) => {
|
|
8
|
+
let astUtils = require_ast_utils$1.t(), BOOLEAN_OPERATORS = new Set([
|
|
9
|
+
"==",
|
|
10
|
+
"===",
|
|
11
|
+
"!=",
|
|
12
|
+
"!==",
|
|
13
|
+
">",
|
|
14
|
+
">=",
|
|
15
|
+
"<",
|
|
16
|
+
"<=",
|
|
17
|
+
"in",
|
|
18
|
+
"instanceof"
|
|
19
|
+
]), OPERATOR_INVERSES = {
|
|
20
|
+
"==": "!=",
|
|
21
|
+
"!=": "==",
|
|
22
|
+
"===": "!==",
|
|
23
|
+
"!==": "==="
|
|
24
|
+
}, OR_PRECEDENCE = astUtils.getPrecedence({
|
|
25
|
+
type: "LogicalExpression",
|
|
26
|
+
operator: "||"
|
|
27
|
+
});
|
|
28
|
+
/** @type {import('../types').Rule.RuleModule} */
|
|
29
|
+
module.exports = {
|
|
30
|
+
meta: {
|
|
31
|
+
type: "suggestion",
|
|
32
|
+
defaultOptions: [{ defaultAssignment: !0 }],
|
|
33
|
+
docs: {
|
|
34
|
+
description: "Disallow ternary operators when simpler alternatives exist",
|
|
35
|
+
recommended: !1,
|
|
36
|
+
frozen: !0,
|
|
37
|
+
url: "https://eslint.org/docs/latest/rules/no-unneeded-ternary"
|
|
38
|
+
},
|
|
39
|
+
schema: [{
|
|
40
|
+
type: "object",
|
|
41
|
+
properties: { defaultAssignment: { type: "boolean" } },
|
|
42
|
+
additionalProperties: !1
|
|
43
|
+
}],
|
|
44
|
+
fixable: "code",
|
|
45
|
+
messages: {
|
|
46
|
+
unnecessaryConditionalExpression: "Unnecessary use of boolean literals in conditional expression.",
|
|
47
|
+
unnecessaryConditionalAssignment: "Unnecessary use of conditional expression for default assignment."
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
create(context) {
|
|
51
|
+
let [{ defaultAssignment }] = context.options, sourceCode = context.sourceCode;
|
|
52
|
+
/**
|
|
53
|
+
* Test if the node is a boolean literal
|
|
54
|
+
* @param {ASTNode} node The node to report.
|
|
55
|
+
* @returns {boolean} True if the its a boolean literal
|
|
56
|
+
* @private
|
|
57
|
+
*/
|
|
58
|
+
function isBooleanLiteral(node) {
|
|
59
|
+
return node.type === "Literal" && typeof node.value == "boolean";
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Creates an expression that represents the boolean inverse of the expression represented by the original node
|
|
63
|
+
* @param {ASTNode} node A node representing an expression
|
|
64
|
+
* @returns {string} A string representing an inverted expression
|
|
65
|
+
*/
|
|
66
|
+
function invertExpression(node) {
|
|
67
|
+
if (node.type === "BinaryExpression" && Object.hasOwn(OPERATOR_INVERSES, node.operator)) {
|
|
68
|
+
let operatorToken = sourceCode.getFirstTokenBetween(node.left, node.right, (token) => token.value === node.operator), text = sourceCode.getText();
|
|
69
|
+
return text.slice(node.range[0], operatorToken.range[0]) + OPERATOR_INVERSES[node.operator] + text.slice(operatorToken.range[1], node.range[1]);
|
|
70
|
+
}
|
|
71
|
+
return astUtils.getPrecedence(node) < astUtils.getPrecedence({ type: "UnaryExpression" }) ? `!(${astUtils.getParenthesisedText(sourceCode, node)})` : `!${astUtils.getParenthesisedText(sourceCode, node)}`;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Tests if a given node always evaluates to a boolean value
|
|
75
|
+
* @param {ASTNode} node An expression node
|
|
76
|
+
* @returns {boolean} True if it is determined that the node will always evaluate to a boolean value
|
|
77
|
+
*/
|
|
78
|
+
function isBooleanExpression(node) {
|
|
79
|
+
return node.type === "BinaryExpression" && BOOLEAN_OPERATORS.has(node.operator) || node.type === "UnaryExpression" && node.operator === "!";
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Test if the node matches the pattern id ? id : expression
|
|
83
|
+
* @param {ASTNode} node The ConditionalExpression to check.
|
|
84
|
+
* @returns {boolean} True if the pattern is matched, and false otherwise
|
|
85
|
+
* @private
|
|
86
|
+
*/
|
|
87
|
+
function matchesDefaultAssignment(node) {
|
|
88
|
+
return node.test.type === "Identifier" && node.consequent.type === "Identifier" && node.test.name === node.consequent.name;
|
|
89
|
+
}
|
|
90
|
+
return { ConditionalExpression(node) {
|
|
91
|
+
isBooleanLiteral(node.alternate) && isBooleanLiteral(node.consequent) ? context.report({
|
|
92
|
+
node,
|
|
93
|
+
messageId: "unnecessaryConditionalExpression",
|
|
94
|
+
fix(fixer) {
|
|
95
|
+
return node.consequent.value === node.alternate.value ? node.test.type === "Identifier" ? fixer.replaceText(node, node.consequent.value.toString()) : null : node.alternate.value ? fixer.replaceText(node, invertExpression(node.test)) : fixer.replaceText(node, isBooleanExpression(node.test) ? astUtils.getParenthesisedText(sourceCode, node.test) : `!${invertExpression(node.test)}`);
|
|
96
|
+
}
|
|
97
|
+
}) : !defaultAssignment && matchesDefaultAssignment(node) && context.report({
|
|
98
|
+
node,
|
|
99
|
+
messageId: "unnecessaryConditionalAssignment",
|
|
100
|
+
fix(fixer) {
|
|
101
|
+
let alternateText = (astUtils.getPrecedence(node.alternate) < OR_PRECEDENCE || astUtils.isCoalesceExpression(node.alternate)) && !astUtils.isParenthesised(sourceCode, node.alternate) ? `(${sourceCode.getText(node.alternate)})` : astUtils.getParenthesisedText(sourceCode, node.alternate), testText = astUtils.getParenthesisedText(sourceCode, node.test);
|
|
102
|
+
return fixer.replaceText(node, `${testText} || ${alternateText}`);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
} };
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
}));
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src-js/generated/plugin-eslint/rules/no-unneeded-ternary.cjs
|
|
111
|
+
module.exports = require_no_unneeded_ternary().create;
|
|
112
|
+
//#endregion
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
//#region ../../node_modules/.pnpm/eslint@9.39.3_jiti@2.6.1/node_modules/eslint/lib/rules/no-unreachable-loop.js
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Rule to disallow loops with a body that allows only one iteration
|
|
4
|
+
* @author Milos Djermanovic
|
|
5
|
+
*/
|
|
6
|
+
var require_no_unreachable_loop = /* @__PURE__ */ require("../common/chunk.cjs").t(((exports, module) => {
|
|
7
|
+
let allLoopTypes = [
|
|
8
|
+
"WhileStatement",
|
|
9
|
+
"DoWhileStatement",
|
|
10
|
+
"ForStatement",
|
|
11
|
+
"ForInStatement",
|
|
12
|
+
"ForOfStatement"
|
|
13
|
+
];
|
|
14
|
+
/**
|
|
15
|
+
* Checks all segments in a set and returns true if any are reachable.
|
|
16
|
+
* @param {Set<CodePathSegment>} segments The segments to check.
|
|
17
|
+
* @returns {boolean} True if any segment is reachable; false otherwise.
|
|
18
|
+
*/
|
|
19
|
+
function isAnySegmentReachable(segments) {
|
|
20
|
+
for (let segment of segments) if (segment.reachable) return !0;
|
|
21
|
+
return !1;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Determines whether the given node is the first node in the code path to which a loop statement
|
|
25
|
+
* 'loops' for the next iteration.
|
|
26
|
+
* @param {ASTNode} node The node to check.
|
|
27
|
+
* @returns {boolean} `true` if the node is a looping target.
|
|
28
|
+
*/
|
|
29
|
+
function isLoopingTarget(node) {
|
|
30
|
+
let parent = node.parent;
|
|
31
|
+
if (parent) switch (parent.type) {
|
|
32
|
+
case "WhileStatement": return node === parent.test;
|
|
33
|
+
case "DoWhileStatement": return node === parent.body;
|
|
34
|
+
case "ForStatement": return node === (parent.update || parent.test || parent.body);
|
|
35
|
+
case "ForInStatement":
|
|
36
|
+
case "ForOfStatement": return node === parent.left;
|
|
37
|
+
}
|
|
38
|
+
return !1;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates an array with elements from the first given array that are not included in the second given array.
|
|
42
|
+
* @param {Array} arrA The array to compare from.
|
|
43
|
+
* @param {Array} arrB The array to compare against.
|
|
44
|
+
* @returns {Array} a new array that represents `arrA \ arrB`.
|
|
45
|
+
*/
|
|
46
|
+
function getDifference(arrA, arrB) {
|
|
47
|
+
return arrA.filter((a) => !arrB.includes(a));
|
|
48
|
+
}
|
|
49
|
+
/** @type {import('../types').Rule.RuleModule} */
|
|
50
|
+
module.exports = {
|
|
51
|
+
meta: {
|
|
52
|
+
type: "problem",
|
|
53
|
+
defaultOptions: [{ ignore: [] }],
|
|
54
|
+
docs: {
|
|
55
|
+
description: "Disallow loops with a body that allows only one iteration",
|
|
56
|
+
recommended: !1,
|
|
57
|
+
url: "https://eslint.org/docs/latest/rules/no-unreachable-loop"
|
|
58
|
+
},
|
|
59
|
+
schema: [{
|
|
60
|
+
type: "object",
|
|
61
|
+
properties: { ignore: {
|
|
62
|
+
type: "array",
|
|
63
|
+
items: { enum: allLoopTypes },
|
|
64
|
+
uniqueItems: !0
|
|
65
|
+
} },
|
|
66
|
+
additionalProperties: !1
|
|
67
|
+
}],
|
|
68
|
+
messages: { invalid: "Invalid loop. Its body allows only one iteration." }
|
|
69
|
+
},
|
|
70
|
+
create(context) {
|
|
71
|
+
let [{ ignore: ignoredLoopTypes }] = context.options, loopSelector = getDifference(allLoopTypes, ignoredLoopTypes).join(","), loopsByTargetSegments = /* @__PURE__ */ new Map(), loopsToReport = /* @__PURE__ */ new Set(), codePathSegments = [], currentCodePathSegments = /* @__PURE__ */ new Set();
|
|
72
|
+
return {
|
|
73
|
+
onCodePathStart() {
|
|
74
|
+
codePathSegments.push(currentCodePathSegments), currentCodePathSegments = /* @__PURE__ */ new Set();
|
|
75
|
+
},
|
|
76
|
+
onCodePathEnd() {
|
|
77
|
+
currentCodePathSegments = codePathSegments.pop();
|
|
78
|
+
},
|
|
79
|
+
onUnreachableCodePathSegmentStart(segment) {
|
|
80
|
+
currentCodePathSegments.add(segment);
|
|
81
|
+
},
|
|
82
|
+
onUnreachableCodePathSegmentEnd(segment) {
|
|
83
|
+
currentCodePathSegments.delete(segment);
|
|
84
|
+
},
|
|
85
|
+
onCodePathSegmentEnd(segment) {
|
|
86
|
+
currentCodePathSegments.delete(segment);
|
|
87
|
+
},
|
|
88
|
+
onCodePathSegmentStart(segment, node) {
|
|
89
|
+
if (currentCodePathSegments.add(segment), isLoopingTarget(node)) {
|
|
90
|
+
let loop = node.parent;
|
|
91
|
+
loopsByTargetSegments.set(segment, loop);
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
onCodePathSegmentLoop(_, toSegment, node) {
|
|
95
|
+
let loop = loopsByTargetSegments.get(toSegment);
|
|
96
|
+
/**
|
|
97
|
+
* The second iteration is reachable, meaning that the loop is valid by the logic of this rule,
|
|
98
|
+
* only if there is at least one loop event with the appropriate target (which has been already
|
|
99
|
+
* determined in the `loopsByTargetSegments` map), raised from either:
|
|
100
|
+
*
|
|
101
|
+
* - the end of the loop's body (in which case `node === loop`)
|
|
102
|
+
* - a `continue` statement
|
|
103
|
+
*
|
|
104
|
+
* This condition skips loop events raised from `ForInStatement > .right` and `ForOfStatement > .right` nodes.
|
|
105
|
+
*/
|
|
106
|
+
(node === loop || node.type === "ContinueStatement") && loopsToReport.delete(loop);
|
|
107
|
+
},
|
|
108
|
+
[loopSelector](node) {
|
|
109
|
+
/**
|
|
110
|
+
* Ignore unreachable loop statements to avoid unnecessary complexity in the implementation, or false positives otherwise.
|
|
111
|
+
* For unreachable segments, the code path analysis does not raise events required for this implementation.
|
|
112
|
+
*/
|
|
113
|
+
isAnySegmentReachable(currentCodePathSegments) && loopsToReport.add(node);
|
|
114
|
+
},
|
|
115
|
+
"Program:exit"() {
|
|
116
|
+
loopsToReport.forEach((node) => context.report({
|
|
117
|
+
node,
|
|
118
|
+
messageId: "invalid"
|
|
119
|
+
}));
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}));
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region src-js/generated/plugin-eslint/rules/no-unreachable-loop.cjs
|
|
127
|
+
module.exports = require_no_unreachable_loop().create;
|
|
128
|
+
//#endregion
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
//#region ../../node_modules/.pnpm/eslint@9.39.3_jiti@2.6.1/node_modules/eslint/lib/rules/no-unreachable.js
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Checks for unreachable code due to return, throws, break, and continue.
|
|
4
|
+
* @author Joel Feenstra
|
|
5
|
+
*/
|
|
6
|
+
var require_no_unreachable = /* @__PURE__ */ require("../common/chunk.cjs").t(((exports, module) => {
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {Object} ConstructorInfo
|
|
9
|
+
* @property {ConstructorInfo | null} upper Info about the constructor that encloses this constructor.
|
|
10
|
+
* @property {boolean} hasSuperCall The flag about having `super()` expressions.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Checks whether or not a given variable declarator has the initializer.
|
|
14
|
+
* @param {ASTNode} node A VariableDeclarator node to check.
|
|
15
|
+
* @returns {boolean} `true` if the node has the initializer.
|
|
16
|
+
*/
|
|
17
|
+
function isInitialized(node) {
|
|
18
|
+
return !!node.init;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Checks all segments in a set and returns true if all are unreachable.
|
|
22
|
+
* @param {Set<CodePathSegment>} segments The segments to check.
|
|
23
|
+
* @returns {boolean} True if all segments are unreachable; false otherwise.
|
|
24
|
+
*/
|
|
25
|
+
function areAllSegmentsUnreachable(segments) {
|
|
26
|
+
for (let segment of segments) if (segment.reachable) return !1;
|
|
27
|
+
return !0;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The class to distinguish consecutive unreachable statements.
|
|
31
|
+
*/
|
|
32
|
+
var ConsecutiveRange = class {
|
|
33
|
+
constructor(sourceCode) {
|
|
34
|
+
this.sourceCode = sourceCode, this.startNode = null, this.endNode = null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The location object of this range.
|
|
38
|
+
* @type {Object}
|
|
39
|
+
*/
|
|
40
|
+
get location() {
|
|
41
|
+
return {
|
|
42
|
+
start: this.startNode.loc.start,
|
|
43
|
+
end: this.endNode.loc.end
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* `true` if this range is empty.
|
|
48
|
+
* @type {boolean}
|
|
49
|
+
*/
|
|
50
|
+
get isEmpty() {
|
|
51
|
+
return !(this.startNode && this.endNode);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Checks whether the given node is inside of this range.
|
|
55
|
+
* @param {ASTNode|Token} node The node to check.
|
|
56
|
+
* @returns {boolean} `true` if the node is inside of this range.
|
|
57
|
+
*/
|
|
58
|
+
contains(node) {
|
|
59
|
+
return node.range[0] >= this.startNode.range[0] && node.range[1] <= this.endNode.range[1];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Checks whether the given node is consecutive to this range.
|
|
63
|
+
* @param {ASTNode} node The node to check.
|
|
64
|
+
* @returns {boolean} `true` if the node is consecutive to this range.
|
|
65
|
+
*/
|
|
66
|
+
isConsecutive(node) {
|
|
67
|
+
return this.contains(this.sourceCode.getTokenBefore(node));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Merges the given node to this range.
|
|
71
|
+
* @param {ASTNode} node The node to merge.
|
|
72
|
+
* @returns {void}
|
|
73
|
+
*/
|
|
74
|
+
merge(node) {
|
|
75
|
+
this.endNode = node;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Resets this range by the given node or null.
|
|
79
|
+
* @param {ASTNode|null} node The node to reset, or null.
|
|
80
|
+
* @returns {void}
|
|
81
|
+
*/
|
|
82
|
+
reset(node) {
|
|
83
|
+
this.startNode = this.endNode = node;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
/** @type {import('../types').Rule.RuleModule} */
|
|
87
|
+
module.exports = {
|
|
88
|
+
meta: {
|
|
89
|
+
type: "problem",
|
|
90
|
+
docs: {
|
|
91
|
+
description: "Disallow unreachable code after `return`, `throw`, `continue`, and `break` statements",
|
|
92
|
+
recommended: !0,
|
|
93
|
+
url: "https://eslint.org/docs/latest/rules/no-unreachable"
|
|
94
|
+
},
|
|
95
|
+
schema: [],
|
|
96
|
+
messages: { unreachableCode: "Unreachable code." }
|
|
97
|
+
},
|
|
98
|
+
create(context) {
|
|
99
|
+
/** @type {ConstructorInfo | null} */
|
|
100
|
+
let constructorInfo = null, range = new ConsecutiveRange(context.sourceCode), codePathSegments = [], currentCodePathSegments = /* @__PURE__ */ new Set();
|
|
101
|
+
/**
|
|
102
|
+
* Reports a given node if it's unreachable.
|
|
103
|
+
* @param {ASTNode} node A statement node to report.
|
|
104
|
+
* @returns {void}
|
|
105
|
+
*/
|
|
106
|
+
function reportIfUnreachable(node) {
|
|
107
|
+
let nextNode = null;
|
|
108
|
+
if (node && (node.type === "PropertyDefinition" || areAllSegmentsUnreachable(currentCodePathSegments))) {
|
|
109
|
+
if (range.isEmpty) {
|
|
110
|
+
range.reset(node);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (range.contains(node)) return;
|
|
114
|
+
if (range.isConsecutive(node)) {
|
|
115
|
+
range.merge(node);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
nextNode = node;
|
|
119
|
+
}
|
|
120
|
+
range.isEmpty || context.report({
|
|
121
|
+
messageId: "unreachableCode",
|
|
122
|
+
loc: range.location,
|
|
123
|
+
node: range.startNode
|
|
124
|
+
}), range.reset(nextNode);
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
onCodePathStart() {
|
|
128
|
+
codePathSegments.push(currentCodePathSegments), currentCodePathSegments = /* @__PURE__ */ new Set();
|
|
129
|
+
},
|
|
130
|
+
onCodePathEnd() {
|
|
131
|
+
currentCodePathSegments = codePathSegments.pop();
|
|
132
|
+
},
|
|
133
|
+
onUnreachableCodePathSegmentStart(segment) {
|
|
134
|
+
currentCodePathSegments.add(segment);
|
|
135
|
+
},
|
|
136
|
+
onUnreachableCodePathSegmentEnd(segment) {
|
|
137
|
+
currentCodePathSegments.delete(segment);
|
|
138
|
+
},
|
|
139
|
+
onCodePathSegmentEnd(segment) {
|
|
140
|
+
currentCodePathSegments.delete(segment);
|
|
141
|
+
},
|
|
142
|
+
onCodePathSegmentStart(segment) {
|
|
143
|
+
currentCodePathSegments.add(segment);
|
|
144
|
+
},
|
|
145
|
+
BlockStatement: reportIfUnreachable,
|
|
146
|
+
BreakStatement: reportIfUnreachable,
|
|
147
|
+
ClassDeclaration: reportIfUnreachable,
|
|
148
|
+
ContinueStatement: reportIfUnreachable,
|
|
149
|
+
DebuggerStatement: reportIfUnreachable,
|
|
150
|
+
DoWhileStatement: reportIfUnreachable,
|
|
151
|
+
ExpressionStatement: reportIfUnreachable,
|
|
152
|
+
ForInStatement: reportIfUnreachable,
|
|
153
|
+
ForOfStatement: reportIfUnreachable,
|
|
154
|
+
ForStatement: reportIfUnreachable,
|
|
155
|
+
IfStatement: reportIfUnreachable,
|
|
156
|
+
ImportDeclaration: reportIfUnreachable,
|
|
157
|
+
LabeledStatement: reportIfUnreachable,
|
|
158
|
+
ReturnStatement: reportIfUnreachable,
|
|
159
|
+
SwitchStatement: reportIfUnreachable,
|
|
160
|
+
ThrowStatement: reportIfUnreachable,
|
|
161
|
+
TryStatement: reportIfUnreachable,
|
|
162
|
+
VariableDeclaration(node) {
|
|
163
|
+
(node.kind !== "var" || node.declarations.some(isInitialized)) && reportIfUnreachable(node);
|
|
164
|
+
},
|
|
165
|
+
WhileStatement: reportIfUnreachable,
|
|
166
|
+
WithStatement: reportIfUnreachable,
|
|
167
|
+
ExportNamedDeclaration: reportIfUnreachable,
|
|
168
|
+
ExportDefaultDeclaration: reportIfUnreachable,
|
|
169
|
+
ExportAllDeclaration: reportIfUnreachable,
|
|
170
|
+
"Program:exit"() {
|
|
171
|
+
reportIfUnreachable();
|
|
172
|
+
},
|
|
173
|
+
"MethodDefinition[kind='constructor']"() {
|
|
174
|
+
constructorInfo = {
|
|
175
|
+
upper: constructorInfo,
|
|
176
|
+
hasSuperCall: !1
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
"MethodDefinition[kind='constructor']:exit"(node) {
|
|
180
|
+
let { hasSuperCall } = constructorInfo;
|
|
181
|
+
if (constructorInfo = constructorInfo.upper, !node.value.body) return;
|
|
182
|
+
let classDefinition = node.parent.parent;
|
|
183
|
+
if (classDefinition.superClass && !hasSuperCall) for (let element of classDefinition.body.body) element.type === "PropertyDefinition" && !element.static && reportIfUnreachable(element);
|
|
184
|
+
},
|
|
185
|
+
"CallExpression > Super.callee"() {
|
|
186
|
+
constructorInfo && (constructorInfo.hasSuperCall = !0);
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
}));
|
|
192
|
+
//#endregion
|
|
193
|
+
//#region src-js/generated/plugin-eslint/rules/no-unreachable.cjs
|
|
194
|
+
module.exports = require_no_unreachable().create;
|
|
195
|
+
//#endregion
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
//#region ../../node_modules/.pnpm/eslint@9.39.3_jiti@2.6.1/node_modules/eslint/lib/rules/no-unsafe-finally.js
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Rule to flag unsafe statements in finally block
|
|
4
|
+
* @author Onur Temizkan
|
|
5
|
+
*/
|
|
6
|
+
var require_no_unsafe_finally = /* @__PURE__ */ require("../common/chunk.cjs").t(((exports, module) => {
|
|
7
|
+
let SENTINEL_NODE_TYPE_RETURN_THROW = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression)$/u, SENTINEL_NODE_TYPE_BREAK = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement|SwitchStatement)$/u, SENTINEL_NODE_TYPE_CONTINUE = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement)$/u;
|
|
8
|
+
/** @type {import('../types').Rule.RuleModule} */
|
|
9
|
+
module.exports = {
|
|
10
|
+
meta: {
|
|
11
|
+
type: "problem",
|
|
12
|
+
docs: {
|
|
13
|
+
description: "Disallow control flow statements in `finally` blocks",
|
|
14
|
+
recommended: !0,
|
|
15
|
+
url: "https://eslint.org/docs/latest/rules/no-unsafe-finally"
|
|
16
|
+
},
|
|
17
|
+
schema: [],
|
|
18
|
+
messages: { unsafeUsage: "Unsafe usage of {{nodeType}}." }
|
|
19
|
+
},
|
|
20
|
+
create(context) {
|
|
21
|
+
/**
|
|
22
|
+
* Checks if the node is the finalizer of a TryStatement
|
|
23
|
+
* @param {ASTNode} node node to check.
|
|
24
|
+
* @returns {boolean} - true if the node is the finalizer of a TryStatement
|
|
25
|
+
*/
|
|
26
|
+
function isFinallyBlock(node) {
|
|
27
|
+
return node.parent.type === "TryStatement" && node.parent.finalizer === node;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Climbs up the tree if the node is not a sentinel node
|
|
31
|
+
* @param {ASTNode} node node to check.
|
|
32
|
+
* @param {string} label label of the break or continue statement
|
|
33
|
+
* @returns {boolean} - return whether the node is a finally block or a sentinel node
|
|
34
|
+
*/
|
|
35
|
+
function isInFinallyBlock(node, label) {
|
|
36
|
+
let labelInside = !1, sentinelNodeType;
|
|
37
|
+
sentinelNodeType = node.type === "BreakStatement" && !node.label ? SENTINEL_NODE_TYPE_BREAK : node.type === "ContinueStatement" ? SENTINEL_NODE_TYPE_CONTINUE : SENTINEL_NODE_TYPE_RETURN_THROW;
|
|
38
|
+
for (let currentNode = node; currentNode && !sentinelNodeType.test(currentNode.type); currentNode = currentNode.parent) if (currentNode.parent.label && label && currentNode.parent.label.name === label.name && (labelInside = !0), isFinallyBlock(currentNode)) return !(label && labelInside);
|
|
39
|
+
return !1;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Checks whether the possibly-unsafe statement is inside a finally block.
|
|
43
|
+
* @param {ASTNode} node node to check.
|
|
44
|
+
* @returns {void}
|
|
45
|
+
*/
|
|
46
|
+
function check(node) {
|
|
47
|
+
isInFinallyBlock(node, node.label) && context.report({
|
|
48
|
+
messageId: "unsafeUsage",
|
|
49
|
+
data: { nodeType: node.type },
|
|
50
|
+
node,
|
|
51
|
+
line: node.loc.line,
|
|
52
|
+
column: node.loc.column
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
ReturnStatement: check,
|
|
57
|
+
ThrowStatement: check,
|
|
58
|
+
BreakStatement: check,
|
|
59
|
+
ContinueStatement: check
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}));
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src-js/generated/plugin-eslint/rules/no-unsafe-finally.cjs
|
|
66
|
+
module.exports = require_no_unsafe_finally().create;
|
|
67
|
+
//#endregion
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
const require_chunk = require("../common/chunk.cjs"), require_ast_utils$1 = require("../common/ast-utils.cjs");
|
|
2
|
+
//#region ../../node_modules/.pnpm/eslint@9.39.3_jiti@2.6.1/node_modules/eslint/lib/rules/no-unsafe-negation.js
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Rule to disallow negating the left operand of relational operators
|
|
5
|
+
* @author Toru Nagashima
|
|
6
|
+
*/
|
|
7
|
+
var require_no_unsafe_negation = /* @__PURE__ */ require_chunk.t(((exports, module) => {
|
|
8
|
+
let astUtils = require_ast_utils$1.t();
|
|
9
|
+
/**
|
|
10
|
+
* Checks whether the given operator is `in` or `instanceof`
|
|
11
|
+
* @param {string} op The operator type to check.
|
|
12
|
+
* @returns {boolean} `true` if the operator is `in` or `instanceof`
|
|
13
|
+
*/
|
|
14
|
+
function isInOrInstanceOfOperator(op) {
|
|
15
|
+
return op === "in" || op === "instanceof";
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Checks whether the given operator is an ordering relational operator or not.
|
|
19
|
+
* @param {string} op The operator type to check.
|
|
20
|
+
* @returns {boolean} `true` if the operator is an ordering relational operator.
|
|
21
|
+
*/
|
|
22
|
+
function isOrderingRelationalOperator(op) {
|
|
23
|
+
return op === "<" || op === ">" || op === ">=" || op === "<=";
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Checks whether the given node is a logical negation expression or not.
|
|
27
|
+
* @param {ASTNode} node The node to check.
|
|
28
|
+
* @returns {boolean} `true` if the node is a logical negation expression.
|
|
29
|
+
*/
|
|
30
|
+
function isNegation(node) {
|
|
31
|
+
return node.type === "UnaryExpression" && node.operator === "!";
|
|
32
|
+
}
|
|
33
|
+
/** @type {import('../types').Rule.RuleModule} */
|
|
34
|
+
module.exports = {
|
|
35
|
+
meta: {
|
|
36
|
+
type: "problem",
|
|
37
|
+
defaultOptions: [{ enforceForOrderingRelations: !1 }],
|
|
38
|
+
docs: {
|
|
39
|
+
description: "Disallow negating the left operand of relational operators",
|
|
40
|
+
recommended: !0,
|
|
41
|
+
url: "https://eslint.org/docs/latest/rules/no-unsafe-negation"
|
|
42
|
+
},
|
|
43
|
+
hasSuggestions: !0,
|
|
44
|
+
schema: [{
|
|
45
|
+
type: "object",
|
|
46
|
+
properties: { enforceForOrderingRelations: { type: "boolean" } },
|
|
47
|
+
additionalProperties: !1
|
|
48
|
+
}],
|
|
49
|
+
fixable: null,
|
|
50
|
+
messages: {
|
|
51
|
+
unexpected: "Unexpected negating the left operand of '{{operator}}' operator.",
|
|
52
|
+
suggestNegatedExpression: "Negate '{{operator}}' expression instead of its left operand. This changes the current behavior.",
|
|
53
|
+
suggestParenthesisedNegation: "Wrap negation in '()' to make the intention explicit. This preserves the current behavior."
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
create(context) {
|
|
57
|
+
let sourceCode = context.sourceCode, [{ enforceForOrderingRelations }] = context.options;
|
|
58
|
+
return { BinaryExpression(node) {
|
|
59
|
+
let operator = node.operator, orderingRelationRuleApplies = enforceForOrderingRelations && isOrderingRelationalOperator(operator);
|
|
60
|
+
(isInOrInstanceOfOperator(operator) || orderingRelationRuleApplies) && isNegation(node.left) && !astUtils.isParenthesised(sourceCode, node.left) && context.report({
|
|
61
|
+
node,
|
|
62
|
+
loc: node.left.loc,
|
|
63
|
+
messageId: "unexpected",
|
|
64
|
+
data: { operator },
|
|
65
|
+
suggest: [{
|
|
66
|
+
messageId: "suggestNegatedExpression",
|
|
67
|
+
data: { operator },
|
|
68
|
+
fix(fixer) {
|
|
69
|
+
let fixRange = [sourceCode.getFirstToken(node.left).range[1], node.range[1]], text = sourceCode.text.slice(fixRange[0], fixRange[1]);
|
|
70
|
+
return fixer.replaceTextRange(fixRange, `(${text})`);
|
|
71
|
+
}
|
|
72
|
+
}, {
|
|
73
|
+
messageId: "suggestParenthesisedNegation",
|
|
74
|
+
fix(fixer) {
|
|
75
|
+
return fixer.replaceText(node.left, `(${sourceCode.getText(node.left)})`);
|
|
76
|
+
}
|
|
77
|
+
}]
|
|
78
|
+
});
|
|
79
|
+
} };
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}));
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src-js/generated/plugin-eslint/rules/no-unsafe-negation.cjs
|
|
85
|
+
module.exports = require_no_unsafe_negation().create;
|
|
86
|
+
//#endregion
|