]>
git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/rules/no-unused-expressions.js
2 * @fileoverview Flag expressions in statement position that do not side effect
3 * @author Michael Ficarra
7 //------------------------------------------------------------------------------
9 //------------------------------------------------------------------------------
13 * @returns {boolean} `true`.
15 function alwaysTrue() {
21 * @returns {boolean} `false`.
23 function alwaysFalse() {
27 /** @type {import('../shared/types').Rule} */
33 description
: "Disallow unused expressions",
35 url
: "https://eslint.org/docs/latest/rules/no-unused-expressions"
50 allowTaggedTemplates
: {
59 additionalProperties
: false
64 unusedExpression
: "Expected an assignment or function call and instead saw an expression."
69 const config
= context
.options
[0] || {},
70 allowShortCircuit
= config
.allowShortCircuit
|| false,
71 allowTernary
= config
.allowTernary
|| false,
72 allowTaggedTemplates
= config
.allowTaggedTemplates
|| false,
73 enforceForJSX
= config
.enforceForJSX
|| false;
76 * Has AST suggesting a directive.
77 * @param {ASTNode} node any node
78 * @returns {boolean} whether the given node structurally represents a directive
80 function looksLikeDirective(node
) {
81 return node
.type
=== "ExpressionStatement" &&
82 node
.expression
.type
=== "Literal" && typeof node
.expression
.value
=== "string";
86 * Gets the leading sequence of members in a list that pass the predicate.
87 * @param {Function} predicate ([a] -> Boolean) the function used to make the determination
88 * @param {a[]} list the input list
89 * @returns {a[]} the leading sequence of members in the given list that pass the given predicate
91 function takeWhile(predicate
, list
) {
92 for (let i
= 0; i
< list
.length
; ++i
) {
93 if (!predicate(list
[i
])) {
94 return list
.slice(0, i
);
101 * Gets leading directives nodes in a Node body.
102 * @param {ASTNode} node a Program or BlockStatement node
103 * @returns {ASTNode[]} the leading sequence of directive nodes in the given node's body
105 function directives(node
) {
106 return takeWhile(looksLikeDirective
, node
.body
);
110 * Detect if a Node is a directive.
111 * @param {ASTNode} node any node
112 * @returns {boolean} whether the given node is considered a directive in its current position
114 function isDirective(node
) {
115 const parent
= node
.parent
,
116 grandparent
= parent
.parent
;
119 * https://tc39.es/ecma262/#directive-prologue
121 * Only `FunctionBody`, `ScriptBody` and `ModuleBody` can have directive prologue.
122 * Class static blocks do not have directive prologue.
124 return (parent
.type
=== "Program" || parent
.type
=== "BlockStatement" &&
125 (/Function/u.test(grandparent
.type
))) &&
126 directives(parent
).includes(node
);
130 * The member functions return `true` if the type has no side-effects.
131 * Unknown nodes are handled as `false`, then this rule ignores those.
133 const Checker
= Object
.assign(Object
.create(null), {
135 return (Checker
[node
.type
] || alwaysFalse
)(node
);
138 ArrayExpression
: alwaysTrue
,
139 ArrowFunctionExpression
: alwaysTrue
,
140 BinaryExpression
: alwaysTrue
,
141 ChainExpression(node
) {
142 return Checker
.isDisallowed(node
.expression
);
144 ClassExpression
: alwaysTrue
,
145 ConditionalExpression(node
) {
147 return Checker
.isDisallowed(node
.consequent
) || Checker
.isDisallowed(node
.alternate
);
151 FunctionExpression
: alwaysTrue
,
152 Identifier
: alwaysTrue
,
154 return enforceForJSX
;
157 return enforceForJSX
;
160 LogicalExpression(node
) {
161 if (allowShortCircuit
) {
162 return Checker
.isDisallowed(node
.right
);
166 MemberExpression
: alwaysTrue
,
167 MetaProperty
: alwaysTrue
,
168 ObjectExpression
: alwaysTrue
,
169 SequenceExpression
: alwaysTrue
,
170 TaggedTemplateExpression() {
171 return !allowTaggedTemplates
;
173 TemplateLiteral
: alwaysTrue
,
174 ThisExpression
: alwaysTrue
,
175 UnaryExpression(node
) {
176 return node
.operator
!== "void" && node
.operator
!== "delete";
181 ExpressionStatement(node
) {
182 if (Checker
.isDisallowed(node
.expression
) && !isDirective(node
)) {
183 context
.report({ node
, messageId
: "unusedExpression" });