Skip to content

Commit 9199611

Browse files
authored
explicit-length-check: Support Vue SFC files (#1360)
1 parent bd3d741 commit 9199611

File tree

5 files changed

+101
-2
lines changed

5 files changed

+101
-2
lines changed

docs/rules/explicit-length-check.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,24 @@ const isEmpty = !(foo.length > 0);
4343
const isEmptySet = !foo.size;
4444
```
4545

46+
```vue
47+
<template>
48+
<div v-if="foo.length">Vue</div>
49+
</template>
50+
```
51+
4652
### Pass
4753

4854
```js
4955
const isEmpty = foo.length === 0;
5056
```
5157

58+
```vue
59+
<template>
60+
<div v-if="foo.length > 0">Vue</div>
61+
</template>
62+
```
63+
5264
## Non-zero comparisons
5365

5466
Enforce comparison with `> 0` when checking for non-zero length.

rules/explicit-length-check.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,11 @@ function create(context) {
141141
];
142142
}
143143

144-
return problem;
144+
// TODO[@fisker]: Make `return problem` work for `vue-eslint-parser`
145+
context.report(problem);
145146
}
146147

147-
return {
148+
const listeners = {
148149
[lengthSelector](lengthNode) {
149150
if (lengthNode.object.type === 'ThisExpression') {
150151
return;
@@ -182,6 +183,13 @@ function create(context) {
182183
}
183184
}
184185
};
186+
187+
// `vue-eslint-parser`
188+
if (context.parserServices && context.parserServices.defineTemplateBodyVisitor) {
189+
return context.parserServices.defineTemplateBodyVisitor(listeners, listeners);
190+
}
191+
192+
return listeners;
185193
}
186194

187195
const schema = [

rules/utils/boolean.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ const isBooleanCall = node =>
1919
node.callee.type === 'Identifier' &&
2020
node.callee.name === 'Boolean' &&
2121
node.arguments.length === 1;
22+
const isVIfAttributeValue = node =>
23+
node &&
24+
node.type === 'VExpressionContainer' &&
25+
node.parent.type === 'VAttribute' &&
26+
node.parent.value === node &&
27+
node.parent.key.type === 'VDirectiveKey' &&
28+
node.parent.key.name.type === 'VIdentifier' &&
29+
(node.parent.key.name.name === 'if' || node.parent.key.name.name === 'else-if');
2230

2331
/**
2432
Check if the value of node is a `boolean`.
@@ -37,6 +45,10 @@ function isBooleanNode(node) {
3745
}
3846

3947
const {parent} = node;
48+
if (isVIfAttributeValue(parent)) {
49+
return true;
50+
}
51+
4052
if (
4153
(
4254
parent.type === 'IfStatement' ||

test/explicit-length-check.mjs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,59 @@ test.snapshot({
202202
'if (foo.size && bar.length) {}'
203203
]
204204
});
205+
206+
test.vue({
207+
valid: [
208+
'<not-template><div v-if="foo.length"></div></not-template>',
209+
'<template><div v-not-if="foo.length"></div></template>',
210+
'<template><div v-if="foo.notLength"></div></template>'
211+
],
212+
invalid: [
213+
{
214+
code: '<template><div v-if="foo.length"></div></template>',
215+
output: '<template><div v-if="foo.length > 0"></div></template>',
216+
errors: 1
217+
},
218+
{
219+
code: outdent`
220+
<template>
221+
<div>
222+
<div v-if="foo"></div>
223+
<div v-else-if="bar.length"></div>
224+
</div>
225+
</template>
226+
`,
227+
output: outdent`
228+
<template>
229+
<div>
230+
<div v-if="foo"></div>
231+
<div v-else-if="bar.length > 0"></div>
232+
</div>
233+
</template>
234+
`,
235+
errors: 1
236+
},
237+
{
238+
code: '<template><div v-if="foo.length"></div></template>',
239+
output: '<template><div v-if="foo.length !== 0"></div></template>',
240+
errors: 1,
241+
options: [{'non-zero': 'not-equal'}]
242+
},
243+
{
244+
code: '<template><div v-if="foo.length"></div></template>',
245+
output: '<template><div v-if="foo.length >= 1"></div></template>',
246+
errors: 1,
247+
options: [{'non-zero': 'greater-than-or-equal'}]
248+
},
249+
{
250+
code: '<template><div v-if="foo.length && bar"></div></template>',
251+
output: '<template><div v-if="foo.length > 0 && bar"></div></template>',
252+
errors: 1
253+
},
254+
{
255+
code: '<script>if (foo.length) {}</script>',
256+
output: '<script>if (foo.length > 0) {}</script>',
257+
errors: 1
258+
}
259+
]
260+
});

test/utils/test.mjs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,16 @@ class Tester {
109109
});
110110
}
111111

112+
vue(tests) {
113+
return this.runTest({
114+
...tests,
115+
testerOptions: {
116+
parser: require.resolve('vue-eslint-parser'),
117+
parserOptions: defaultParserOptions
118+
}
119+
});
120+
}
121+
112122
snapshot(tests) {
113123
const tester = snapshotRuleTester(test, {
114124
parserOptions: defaultParserOptions
@@ -124,6 +134,7 @@ function getTester(importMeta) {
124134
const test = Tester.prototype.runTest.bind(tester);
125135
test.typescript = Tester.prototype.typescript.bind(tester);
126136
test.babel = Tester.prototype.babel.bind(tester);
137+
test.vue = Tester.prototype.vue.bind(tester);
127138
test.snapshot = Tester.prototype.snapshot.bind(tester);
128139

129140
return {

0 commit comments

Comments
 (0)