Skip to content

Commit f4577f7

Browse files
authored
explicit-length-check: Check Boolean(foo.length) (#951)
1 parent 582ca34 commit f4577f7

File tree

5 files changed

+137
-6
lines changed

5 files changed

+137
-6
lines changed

docs/rules/explicit-length-check.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ const isNotEmpty = 0 < foo.length;
7979
const isNotEmpty = 1 <= foo.length;
8080
```
8181

82+
```js
83+
const isNotEmpty = Boolean(foo.length);
84+
```
85+
8286
```js
8387
// Negative style is forbidden too
8488
const isNotEmpty = !(foo.length === 0);

rules/explicit-length-check.js

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,22 @@ const messages = {
1111
};
1212

1313
const isLogicNot = node =>
14+
node &&
1415
node.type === 'UnaryExpression' &&
1516
node.operator === '!';
1617
const isLogicNotArgument = node =>
17-
node.parent &&
1818
isLogicNot(node.parent) &&
1919
node.parent.argument === node;
20+
const isBooleanCall = node =>
21+
node &&
22+
node.type === 'CallExpression' &&
23+
node.callee &&
24+
node.callee.type === 'Identifier' &&
25+
node.callee.name === 'Boolean' &&
26+
node.arguments.length === 1;
27+
const isBooleanCallArgument = node =>
28+
isBooleanCall(node.parent) &&
29+
node.parent.arguments[0] === node;
2030
const isCompareRight = (node, operator, value) =>
2131
node.type === 'BinaryExpression' &&
2232
node.operator === operator &&
@@ -62,9 +72,16 @@ const lengthSelector = [
6272

6373
function getBooleanAncestor(node) {
6474
let isNegative = false;
65-
while (isLogicNotArgument(node)) {
66-
isNegative = !isNegative;
67-
node = node.parent;
75+
// eslint-disable-next-line no-constant-condition
76+
while (true) {
77+
if (isLogicNotArgument(node)) {
78+
isNegative = !isNegative;
79+
node = node.parent;
80+
} else if (isBooleanCallArgument(node)) {
81+
node = node.parent;
82+
} else {
83+
break;
84+
}
6885
}
6986

7087
return {node, isNegative};
@@ -117,7 +134,12 @@ function getLengthCheckNode(node) {
117134
}
118135

119136
function isBooleanNode(node) {
120-
if (isLogicNot(node) || isLogicNotArgument(node)) {
137+
if (
138+
isLogicNot(node) ||
139+
isLogicNotArgument(node) ||
140+
isBooleanCall(node) ||
141+
isBooleanCallArgument(node)
142+
) {
121143
return true;
122144
}
123145

test/explicit-length-check.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ test({
3939
// Not boolean
4040
'const bar = foo.length',
4141
'const bar = +foo.length',
42+
'const x = Boolean(foo.length, foo.length)',
43+
'const x = new Boolean(foo.length)',
44+
'const x = NotBoolean(foo.length)',
4245

4346
// Checking 'non-zero'
4447
'if (foo.length > 0) {}',
@@ -119,5 +122,11 @@ test.visualize([
119122
'const isEmpty = foo.length < 1;',
120123
'bar(foo.length >= 1)',
121124
'bar(!foo.length || foo.length)',
122-
'const bar = void !foo.length;'
125+
'const bar = void !foo.length;',
126+
'const isNotEmpty = Boolean(foo.length)',
127+
'const isNotEmpty = Boolean(foo.length || bar)',
128+
'const isEmpty = Boolean(!foo.length)',
129+
'const isEmpty = Boolean(foo.length === 0)',
130+
'const isNotEmpty = !Boolean(foo.length === 0)',
131+
'const isEmpty = !Boolean(!Boolean(foo.length === 0))'
123132
]);

test/snapshots/explicit-length-check.js.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,3 +891,99 @@ Generated by [AVA](https://avajs.dev).
891891
> 1 | const bar = void !foo.length;␊
892892
| ^^^^^^^^^^^ Use `.length === 0` when checking length is zero.␊
893893
`
894+
895+
## explicit-length-check - #15
896+
897+
> Snapshot 1
898+
899+
`␊
900+
Input:␊
901+
1 | const isNotEmpty = Boolean(foo.length)␊
902+
903+
Output:␊
904+
1 | const isNotEmpty = foo.length > 0␊
905+
906+
Error 1/1:␊
907+
> 1 | const isNotEmpty = Boolean(foo.length)␊
908+
| ^^^^^^^^^^^^^^^^^^^ Use `.length > 0` when checking length is not zero.␊
909+
`
910+
911+
## explicit-length-check - #16
912+
913+
> Snapshot 1
914+
915+
`␊
916+
Input:␊
917+
1 | const isNotEmpty = Boolean(foo.length || bar)␊
918+
919+
Output:␊
920+
1 | const isNotEmpty = Boolean(foo.length > 0 || bar)␊
921+
922+
Error 1/1:␊
923+
> 1 | const isNotEmpty = Boolean(foo.length || bar)␊
924+
| ^^^^^^^^^^ Use `.length > 0` when checking length is not zero.␊
925+
`
926+
927+
## explicit-length-check - #17
928+
929+
> Snapshot 1
930+
931+
`␊
932+
Input:␊
933+
1 | const isEmpty = Boolean(!foo.length)␊
934+
935+
Output:␊
936+
1 | const isEmpty = foo.length === 0␊
937+
938+
Error 1/1:␊
939+
> 1 | const isEmpty = Boolean(!foo.length)␊
940+
| ^^^^^^^^^^^^^^^^^^^^ Use `.length === 0` when checking length is zero.␊
941+
`
942+
943+
## explicit-length-check - #18
944+
945+
> Snapshot 1
946+
947+
`␊
948+
Input:␊
949+
1 | const isEmpty = Boolean(foo.length === 0)␊
950+
951+
Output:␊
952+
1 | const isEmpty = foo.length === 0␊
953+
954+
Error 1/1:␊
955+
> 1 | const isEmpty = Boolean(foo.length === 0)␊
956+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ Use `.length === 0` when checking length is zero.␊
957+
`
958+
959+
## explicit-length-check - #19
960+
961+
> Snapshot 1
962+
963+
`␊
964+
Input:␊
965+
1 | const isNotEmpty = !Boolean(foo.length === 0)␊
966+
967+
Output:␊
968+
1 | const isNotEmpty = foo.length > 0␊
969+
970+
Error 1/1:␊
971+
> 1 | const isNotEmpty = !Boolean(foo.length === 0)␊
972+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `.length > 0` when checking length is not zero.␊
973+
`
974+
975+
## explicit-length-check - #20
976+
977+
> Snapshot 1
978+
979+
`␊
980+
Input:␊
981+
1 | const isEmpty = !Boolean(!Boolean(foo.length === 0))␊
982+
983+
Output:␊
984+
1 | const isEmpty = foo.length === 0␊
985+
986+
Error 1/1:␊
987+
> 1 | const isEmpty = !Boolean(!Boolean(foo.length === 0))␊
988+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `.length === 0` when checking length is zero.␊
989+
`
308 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)