Skip to content

Commit 64342cb

Browse files
authored
Remove use of memberExpressionSelector (#2120)
1 parent 80c81bb commit 64342cb

File tree

4 files changed

+75
-77
lines changed

4 files changed

+75
-77
lines changed

rules/no-useless-length-check.js

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,23 @@
11
'use strict';
2-
const {isMethodCall} = require('./ast/index.js');
3-
const {matches, memberExpressionSelector} = require('./selectors/index.js');
4-
const {getParenthesizedRange, isSameReference} = require('./utils/index.js');
2+
const {isMethodCall, isMemberExpression} = require('./ast/index.js');
3+
const {
4+
getParenthesizedRange,
5+
isSameReference,
6+
isLogicalExpression,
7+
} = require('./utils/index.js');
58

69
const messages = {
710
'non-zero': 'The non-empty check is useless as `Array#some()` returns `false` for an empty array.',
811
zero: 'The empty check is useless as `Array#every()` returns `true` for an empty array.',
912
};
1013

11-
const logicalExpressionSelector = [
12-
'LogicalExpression',
13-
matches(['[operator="||"]', '[operator="&&"]']),
14-
].join('');
1514
// We assume the user already follows `unicorn/explicit-length-check`. These are allowed in that rule.
16-
const lengthCompareZeroSelector = [
17-
logicalExpressionSelector,
18-
' > ',
19-
'BinaryExpression',
20-
memberExpressionSelector({path: 'left', property: 'length'}),
21-
'[right.type="Literal"]',
22-
'[right.raw="0"]',
23-
].join('');
24-
const zeroLengthCheckSelector = [
25-
lengthCompareZeroSelector,
26-
'[operator="==="]',
27-
].join('');
28-
const nonZeroLengthCheckSelector = [
29-
lengthCompareZeroSelector,
30-
matches(['[operator=">"]', '[operator="!=="]']),
31-
].join('');
15+
const isLengthCompareZero = node =>
16+
node.type === 'BinaryExpression'
17+
&& node.right.type === 'Literal'
18+
&& node.right.raw === '0'
19+
&& isMemberExpression(node.left, {property: 'length', optional: false})
20+
&& isLogicalExpression(node.parent);
3221

3322
function flatLogicalExpression(node) {
3423
return [node.left, node.right].flatMap(child =>
@@ -81,11 +70,15 @@ const create = context => {
8170
}
8271

8372
return {
84-
[zeroLengthCheckSelector](node) {
85-
zeroLengthChecks.add(node);
86-
},
87-
[nonZeroLengthCheckSelector](node) {
88-
nonZeroLengthChecks.add(node);
73+
BinaryExpression(node) {
74+
if (isLengthCompareZero(node)) {
75+
const {operator} = node;
76+
if (operator === '===') {
77+
zeroLengthChecks.add(node);
78+
} else if (operator === '>' || operator === '!==') {
79+
nonZeroLengthChecks.add(node);
80+
}
81+
}
8982
},
9083
CallExpression(node) {
9184
if (
@@ -103,8 +96,10 @@ const create = context => {
10396
}
10497
}
10598
},
106-
[logicalExpressionSelector](node) {
107-
logicalExpressions.push(node);
99+
LogicalExpression(node) {
100+
if (isLogicalExpression(node)) {
101+
logicalExpressions.push(node);
102+
}
108103
},
109104
* 'Program:exit'() {
110105
const nodes = new Set(

rules/prefer-top-level-await.js

Lines changed: 49 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22
const {findVariable, getFunctionHeadLocation} = require('@eslint-community/eslint-utils');
3-
const {matches, not, memberExpressionSelector} = require('./selectors/index.js');
3+
const {isFunction, isMemberExpression} = require('./ast/index.js');
44

55
const ERROR_PROMISE = 'promise';
66
const ERROR_IIFE = 'iife';
@@ -14,32 +14,23 @@ const messages = {
1414
};
1515

1616
const promiseMethods = ['then', 'catch', 'finally'];
17+
const isTopLevelCallExpression = node => {
18+
if (node.type !== 'CallExpression') {
19+
return false;
20+
}
1721

18-
const topLevelCallExpression = [
19-
'CallExpression',
20-
not([':function *', 'ClassDeclaration *', 'ClassExpression *']),
21-
].join('');
22-
const iife = [
23-
topLevelCallExpression,
24-
matches([
25-
'[callee.type="FunctionExpression"]',
26-
'[callee.type="ArrowFunctionExpression"]',
27-
]),
28-
'[callee.async!=false]',
29-
'[callee.generator!=true]',
30-
].join('');
31-
const promise = [
32-
topLevelCallExpression,
33-
memberExpressionSelector({
34-
path: 'callee',
35-
properties: promiseMethods,
36-
includeOptional: true,
37-
}),
38-
].join('');
39-
const identifier = [
40-
topLevelCallExpression,
41-
'[callee.type="Identifier"]',
42-
].join('');
22+
for (let ancestor = node.parent; ancestor; ancestor = ancestor.parent) {
23+
if (
24+
isFunction(ancestor)
25+
|| ancestor.type === 'ClassDeclaration'
26+
|| ancestor.type === 'ClassExpression'
27+
) {
28+
return false;
29+
}
30+
}
31+
32+
return true;
33+
};
4334

4435
const isPromiseMethodCalleeObject = node =>
4536
node.parent.type === 'MemberExpression'
@@ -63,32 +54,44 @@ function create(context) {
6354
return;
6455
}
6556

66-
const {sourceCode} = context;
67-
6857
return {
69-
[promise](node) {
70-
if (isPromiseMethodCalleeObject(node) || isAwaitArgument(node)) {
58+
CallExpression(node) {
59+
if (
60+
!isTopLevelCallExpression(node)
61+
|| isPromiseMethodCalleeObject(node)
62+
|| isAwaitArgument(node)
63+
) {
7164
return;
7265
}
7366

74-
return {
75-
node: node.callee.property,
76-
messageId: ERROR_PROMISE,
77-
};
78-
},
79-
[iife](node) {
80-
if (isPromiseMethodCalleeObject(node) || isAwaitArgument(node)) {
81-
return;
67+
// Promises
68+
if (isMemberExpression(node.callee, {
69+
properties: promiseMethods,
70+
computed: false,
71+
})) {
72+
return {
73+
node: node.callee.property,
74+
messageId: ERROR_PROMISE,
75+
};
8276
}
8377

84-
return {
85-
node,
86-
loc: getFunctionHeadLocation(node.callee, sourceCode),
87-
messageId: ERROR_IIFE,
88-
};
89-
},
90-
[identifier](node) {
91-
if (isPromiseMethodCalleeObject(node) || isAwaitArgument(node)) {
78+
const {sourceCode} = context;
79+
80+
// IIFE
81+
if (
82+
(node.callee.type === 'FunctionExpression' || node.callee.type === 'ArrowFunctionExpression')
83+
&& node.callee.async
84+
&& !node.callee.generator
85+
) {
86+
return {
87+
node,
88+
loc: getFunctionHeadLocation(node.callee, sourceCode),
89+
messageId: ERROR_IIFE,
90+
};
91+
}
92+
93+
// Identifier
94+
if (node.callee.type !== 'Identifier') {
9295
return;
9396
}
9497

rules/selectors/index.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ module.exports = {
55
matches: require('./matches-any.js'),
66
not: require('./negation.js'),
77

8-
memberExpressionSelector: require('./member-expression-selector.js'),
98
methodCallSelector: require('./method-call-selector.js'),
109
callExpressionSelector: require('./call-or-new-expression-selector.js').callExpressionSelector,
1110
newExpressionSelector: require('./call-or-new-expression-selector.js').newExpressionSelector,

rules/utils/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ module.exports = {
2424
getVariableIdentifiers: require('./get-variable-identifiers.js'),
2525
isArrayPrototypeProperty,
2626
isBooleanNode,
27+
isLogicalExpression: require('./is-logical-expression.js'),
2728
isNodeMatches,
2829
isNodeMatchesNameOrPath,
2930
isNodeValueNotDomNode: require('./is-node-value-not-dom-node.js'),

0 commit comments

Comments
 (0)