Skip to content

Commit f0249e0

Browse files
jfmengelssindresorhus
authored andcommitted
Add explicit-length-check rule (fixes #12) (#45)
1 parent 48ef6e1 commit f0249e0

File tree

5 files changed

+121
-0
lines changed

5 files changed

+121
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Enforce explicitly comparing the `length` property of a value
2+
3+
Enforce explicitly checking the length of a value array in an `if` condition, rather than checking the truthiness of the length.
4+
5+
## Fail
6+
7+
```js
8+
if (string.length) {}
9+
if (array.length) {}
10+
if (!array.length) {}
11+
```
12+
13+
14+
## Pass
15+
16+
```js
17+
if (string.length > 0) {}
18+
if (array.length > 0) {}
19+
if (array.length !== 0) {}
20+
if (array.length === 0) {}
21+
```

index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module.exports = {
1414
},
1515
rules: {
1616
'xo/catch-error-name': ['error', {name: 'err'}],
17+
'xo/explicit-length-check': 'error',
1718
'xo/filename-case': ['error', {case: 'kebabCase'}],
1819
'xo/no-abusive-eslint-disable': 'error',
1920
'xo/no-process-exit': 'error',

readme.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Configure it in `package.json`.
3232
],
3333
"rules": {
3434
"xo/catch-error-name": ["error", {"name": "err"}],
35+
"xo/explicit-length-check": "error",
3536
"xo/filename-case": ["error", {"case": "kebabCase"}],
3637
"xo/no-abusive-eslint-disable": "error",
3738
"xo/no-process-exit": "error",
@@ -45,6 +46,7 @@ Configure it in `package.json`.
4546
## Rules
4647

4748
- [catch-error-name](docs/rules/catch-error-name.md) - Enforce a specific parameter name in catch clauses.
49+
- [explicit-length-check](docs/rules/explicit-length-check.md) - Enforce explicitly comparing the `length` property of a value.
4850
- [filename-case](docs/rules/filename-case.md) - Enforce a case style for filenames.
4951
- [no-abusive-eslint-disable](docs/rules/no-abusive-eslint-disable.md) - Enforce specifying rules to disable in `eslint-disable` comments.
5052
- [no-process-exit](docs/rules/no-process-exit.md) - Disallow `process.exit()`.

rules/explicit-length-check.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
'use strict';
2+
3+
function checkExpression(context, node) {
4+
if (node.type === 'LogicalExpression') {
5+
checkExpression(context, node.left);
6+
checkExpression(context, node.right);
7+
return;
8+
}
9+
10+
if (node.type === 'UnaryExpression' && node.operator === '!') {
11+
checkExpression(context, node.argument);
12+
return;
13+
}
14+
15+
if (node.type === 'MemberExpression' &&
16+
node.property.type === 'Identifier' &&
17+
node.property.name === 'length'
18+
) {
19+
context.report({
20+
node,
21+
message: '`length` property should be compared to a value'
22+
});
23+
}
24+
}
25+
26+
module.exports = context => {
27+
return {
28+
IfStatement: node => {
29+
checkExpression(context, node.test);
30+
}
31+
};
32+
};

test/explicit-length-check.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import test from 'ava';
2+
import avaRuleTester from 'eslint-ava-rule-tester';
3+
import rule from '../rules/explicit-length-check';
4+
5+
const ruleTester = avaRuleTester(test, {
6+
env: {
7+
es6: true
8+
}
9+
});
10+
11+
const errors = [{
12+
ruleId: 'explicit-length-check',
13+
message: '`length` property should be compared to a value'
14+
}];
15+
16+
ruleTester.run('explicit-length-check', rule, {
17+
valid: [
18+
'array.foo',
19+
'array.length',
20+
'array.length === 0',
21+
'array.length !== 0',
22+
'array.length > 0',
23+
'if (array.foo) {}',
24+
'if (length) {}',
25+
'if ([].length > 0) {}',
26+
'if ("".length > 0) {}',
27+
'if (array.length === 0) {}',
28+
'if (array.length !== 0) {}',
29+
'if (array.length !== 0 && array[0] === 1) {}'
30+
],
31+
invalid: [
32+
{
33+
code: 'if ([].length) {}',
34+
errors
35+
},
36+
{
37+
code: 'if ("".length) {}',
38+
errors
39+
},
40+
{
41+
code: 'if (array.length) {}',
42+
errors
43+
},
44+
{
45+
code: 'if (!array.length) {}',
46+
errors
47+
},
48+
{
49+
code: 'if (array.foo.length) {}',
50+
errors
51+
},
52+
{
53+
code: 'if (!!array.length) {}',
54+
errors
55+
},
56+
{
57+
code: 'if (array.length && array[0] === 1) {}',
58+
errors
59+
},
60+
{
61+
code: 'if (array[0] === 1 || array.length) {}',
62+
errors
63+
}
64+
]
65+
});

0 commit comments

Comments
 (0)