Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 71929fa

Browse files
Add "require-default-prop" rule (fixes #122) (#135)
* Add "require-default-prop" rule * Handle spread operator cases
1 parent b25be73 commit 71929fa

File tree

3 files changed

+256
-0
lines changed

3 files changed

+256
-0
lines changed

‎docs/rules/require-default-prop.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Require default value for props (require-default-prop)
2+
3+
This rule requires default value to be set for each props that are not marked as `required`.
4+
5+
## Rule Details
6+
7+
Examples of **incorrect** code for this rule:
8+
9+
```js
10+
export default {
11+
props: {
12+
a: Number,
13+
b: [Number, String],
14+
c: {
15+
type: Number
16+
},
17+
d: {
18+
type: Number,
19+
required: false
20+
}
21+
}
22+
}
23+
```
24+
25+
Examples of **correct** code for this rule:
26+
27+
```js
28+
export default {
29+
props: {
30+
a: {
31+
type: Number,
32+
required: true
33+
},
34+
b: {
35+
type: Number,
36+
default: 0
37+
},
38+
c: {
39+
type: Number,
40+
default: 0,
41+
required: false
42+
}
43+
}
44+
}
45+
```

‎lib/rules/require-default-prop.js

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/**
2+
* @fileoverview Require default value for props
3+
* @author Michał Sajnóg <msajnog93@gmail.com> (http://github.com/michalsnik)
4+
*/
5+
'use strict'
6+
7+
const utils = require('../utils')
8+
9+
// ------------------------------------------------------------------------------
10+
// Rule Definition
11+
// ------------------------------------------------------------------------------
12+
13+
module.exports = {
14+
meta: {
15+
docs: {
16+
description: 'Require default value for props',
17+
category: 'Best Practices',
18+
recommended: false
19+
},
20+
fixable: null, // or "code" or "whitespace"
21+
schema: []
22+
},
23+
24+
create: function (context) {
25+
// ----------------------------------------------------------------------
26+
// Helpers
27+
// ----------------------------------------------------------------------
28+
29+
/**
30+
* Checks if the passed prop is required
31+
* @param {Property} prop - Property AST node for a single prop
32+
* @return {boolean}
33+
*/
34+
function propIsRequired (prop) {
35+
const propRequiredNode = prop.value.properties
36+
.find(p =>
37+
p.type === 'Property' &&
38+
p.key.name === 'required' &&
39+
p.value.type === 'Literal' &&
40+
p.value.value === true
41+
)
42+
43+
return Boolean(propRequiredNode)
44+
}
45+
46+
/**
47+
* Checks if the passed prop has a defualt value
48+
* @param {Property} prop - Property AST node for a single prop
49+
* @return {boolean}
50+
*/
51+
function propHasDefault (prop) {
52+
const propDefaultNode = prop.value.properties
53+
.find(p => p.key.name === 'default')
54+
55+
return Boolean(propDefaultNode)
56+
}
57+
58+
/**
59+
* Finds all props that don't have a default value set
60+
* @param {Property} propsNode - Vue component's "props" node
61+
* @return {boolean}
62+
*/
63+
function findPropsWithoutDefaultValue (propsNode) {
64+
return propsNode.value.properties
65+
.filter(prop => prop.type === 'Property')
66+
.filter(prop => {
67+
if (prop.value.type !== 'ObjectExpression') {
68+
return true
69+
}
70+
71+
return !propIsRequired(prop) && !propHasDefault(prop)
72+
})
73+
}
74+
75+
// ----------------------------------------------------------------------
76+
// Public
77+
// ----------------------------------------------------------------------
78+
79+
return utils.executeOnVue(context, (obj) => {
80+
const propsNode = obj.properties
81+
.find(p =>
82+
p.type === 'Property' &&
83+
p.key.type === 'Identifier' &&
84+
p.key.name === 'props' &&
85+
p.value.type === 'ObjectExpression'
86+
)
87+
88+
if (!propsNode) return
89+
90+
const propsWithoutDefault = findPropsWithoutDefaultValue(propsNode)
91+
92+
propsWithoutDefault.forEach(prop => {
93+
context.report({
94+
node: prop,
95+
message: `Prop '{{propName}}' requires default value to be set.`,
96+
data: {
97+
propName: prop.key.name
98+
}
99+
})
100+
})
101+
})
102+
}
103+
}

‎tests/lib/rules/require-default-prop.js

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/**
2+
* @fileoverview Require default value for props
3+
* @author Michał Sajnóg <msajnog93@gmail.com> (http://github.com/michalsnik)
4+
*/
5+
'use strict'
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
const rule = require('../../../lib/rules/require-default-prop')
12+
const RuleTester = require('eslint').RuleTester
13+
const parserOptions = {
14+
ecmaVersion: 6,
15+
ecmaFeatures: { experimentalObjectRestSpread: true },
16+
sourceType: 'module'
17+
}
18+
19+
// ------------------------------------------------------------------------------
20+
// Tests
21+
// ------------------------------------------------------------------------------
22+
23+
const ruleTester = new RuleTester()
24+
ruleTester.run('require-default-prop', rule, {
25+
26+
valid: [
27+
{
28+
filename: 'test.vue',
29+
code: `
30+
export default {
31+
props: {
32+
a: {
33+
type: Number,
34+
required: true
35+
},
36+
b: {
37+
type: Number,
38+
default: 0
39+
},
40+
c: {
41+
type: Number,
42+
default: 0,
43+
required: false
44+
},
45+
// eslint-disable-next-line require-default-prop
46+
d: Number
47+
}
48+
}
49+
`,
50+
parserOptions
51+
},
52+
{
53+
filename: 'test.vue',
54+
code: `
55+
export default {
56+
props: {
57+
...x,
58+
a: {
59+
...y,
60+
type: Number,
61+
required: true
62+
},
63+
b: {
64+
type: Number,
65+
default: 0
66+
}
67+
}
68+
}
69+
`,
70+
parserOptions
71+
}
72+
],
73+
74+
invalid: [
75+
{
76+
filename: 'test.vue',
77+
code: `
78+
export default {
79+
props: {
80+
a: Number,
81+
b: [Number, String],
82+
c: {
83+
type: Number
84+
},
85+
d: {
86+
type: Number,
87+
required: false
88+
}
89+
}
90+
}
91+
`,
92+
parserOptions,
93+
errors: [{
94+
message: `Prop 'a' requires default value to be set.`,
95+
line: 4
96+
}, {
97+
message: `Prop 'b' requires default value to be set.`,
98+
line: 5
99+
}, {
100+
message: `Prop 'c' requires default value to be set.`,
101+
line: 6
102+
}, {
103+
message: `Prop 'd' requires default value to be set.`,
104+
line: 9
105+
}]
106+
}
107+
]
108+
})

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /