]>
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() {
32 description
: "disallow unused expressions",
33 category
: "Best Practices",
35 url
: "https://eslint.org/docs/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;
75 // eslint-disable-next-line jsdoc/require-description
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";
85 // eslint-disable-next-line jsdoc/require-description
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
);
100 // eslint-disable-next-line jsdoc/require-description
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
);
109 // eslint-disable-next-line jsdoc/require-description
111 * @param {ASTNode} node any node
112 * @param {ASTNode[]} ancestors the given node's ancestors
113 * @returns {boolean} whether the given node is considered a directive in its current position
115 function isDirective(node
, ancestors
) {
116 const parent
= ancestors
[ancestors
.length
- 1],
117 grandparent
= ancestors
[ancestors
.length
- 2];
119 return (parent
.type
=== "Program" || parent
.type
=== "BlockStatement" &&
120 (/Function/u.test(grandparent
.type
))) &&
121 directives(parent
).indexOf(node
) >= 0;
125 * The member functions return `true` if the type has no side-effects.
126 * Unknown nodes are handled as `false`, then this rule ignores those.
128 const Checker
= Object
.assign(Object
.create(null), {
130 return (Checker
[node
.type
] || alwaysFalse
)(node
);
133 ArrayExpression
: alwaysTrue
,
134 ArrowFunctionExpression
: alwaysTrue
,
135 BinaryExpression
: alwaysTrue
,
136 ChainExpression(node
) {
137 return Checker
.isDisallowed(node
.expression
);
139 ClassExpression
: alwaysTrue
,
140 ConditionalExpression(node
) {
142 return Checker
.isDisallowed(node
.consequent
) || Checker
.isDisallowed(node
.alternate
);
146 FunctionExpression
: alwaysTrue
,
147 Identifier
: alwaysTrue
,
149 return enforceForJSX
;
152 return enforceForJSX
;
155 LogicalExpression(node
) {
156 if (allowShortCircuit
) {
157 return Checker
.isDisallowed(node
.right
);
161 MemberExpression
: alwaysTrue
,
162 MetaProperty
: alwaysTrue
,
163 ObjectExpression
: alwaysTrue
,
164 SequenceExpression
: alwaysTrue
,
165 TaggedTemplateExpression() {
166 return !allowTaggedTemplates
;
168 TemplateLiteral
: alwaysTrue
,
169 ThisExpression
: alwaysTrue
,
170 UnaryExpression(node
) {
171 return node
.operator
!== "void" && node
.operator
!== "delete";
176 ExpressionStatement(node
) {
177 if (Checker
.isDisallowed(node
.expression
) && !isDirective(node
, context
.getAncestors())) {
178 context
.report({ node
, messageId
: "unusedExpression" });