UNPKG

1.72 kBJavaScriptView Raw
1"use strict";
2
3const ruleComposer = require('eslint-rule-composer');
4const eslint = require('eslint');
5const rule = new eslint.Linter().getRules().get('no-unused-expressions');
6
7/**
8 * @param {ASTNode} node - any node
9 * @returns {boolean} whether the given node is either an IfStatement or an
10 * ExpressionStatement and is the last node in the body of a BlockStatement
11 */
12function isFinalStatementInBlockStatement(node) {
13 const parent = node.parent;
14 return /^(?:If|Expression)Statement$/.test(node.type) &&
15 parent.type === 'BlockStatement' &&
16 parent.body[parent.body.length - 1] === node;
17}
18
19/**
20 * @param {ASTNode} node - any node
21 * @returns {boolean} whether the given node represents an unbroken chain of
22 * tail ExpressionStatements and IfStatements within a DoExpression
23 */
24function isInDoStatement(node) {
25 if (!node) return false;
26
27 if (node.type === 'DoExpression') return true;
28
29 // this is an `else if`
30 if (
31 node.type === 'IfStatement' &&
32 node.parent &&
33 node.parent.type === 'IfStatement'
34 ) {
35 return isInDoStatement(node.parent);
36 }
37
38 if (isFinalStatementInBlockStatement(node)) {
39 return isInDoStatement(node.parent.parent);
40 }
41
42 return false;
43}
44
45/**
46 * @param {ASTNode} node - any node
47 * @returns {boolean} whether the given node is an optional call expression,
48 * see https://github.com/tc39/proposal-optional-chaining
49 */
50function isOptionalCallExpression(node) {
51 return (
52 !!node &&
53 node.type === 'ExpressionStatement' &&
54 node.expression.type === 'OptionalCallExpression'
55 );
56}
57
58module.exports = ruleComposer.filterReports(
59 rule,
60 (problem, metadata) =>
61 !isInDoStatement(problem.node) && !isOptionalCallExpression(problem.node)
62);
63