/
prefer-optional-props-using-with-defaults.js
96 lines (89 loc) · 2.9 KB
/
prefer-optional-props-using-with-defaults.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/**
* @author @neferqiqi
* See LICENSE file in root directory for full license.
*/
'use strict'
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const utils = require('../utils')
/**
* @typedef {import('../utils').ComponentTypeProp} ComponentTypeProp
*/
// ------------------------------------------------------------------------------
// Helpers
// ------------------------------------------------------------------------------
// ...
// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
module.exports = {
meta: {
type: 'suggestion',
docs: {
description: 'enforce props with default values to be optional',
categories: undefined,
url: 'https://eslint.vuejs.org/rules/prefer-optional-props-using-with-defaults.html'
},
fixable: 'code',
schema: [],
messages: {
// ...
}
},
/** @param {RuleContext} context */
create(context) {
/**
* @param {ComponentTypeProp} prop
* @param {Token[]} tokens
* */
const findKeyToken = (prop, tokens) =>
tokens.find((token) => {
const isKeyIdentifierEqual =
prop.key.type === 'Identifier' && token.value === prop.key.name
const isKeyLiteralEqual =
prop.key.type === 'Literal' && token.value === prop.key.raw
return isKeyIdentifierEqual || isKeyLiteralEqual
})
return utils.defineScriptSetupVisitor(context, {
onDefinePropsEnter(node, props) {
if (!utils.hasWithDefaults(node)) {
return
}
const withDefaultsProps = Object.keys(
utils.getWithDefaultsPropExpressions(node)
)
const requiredProps = props.flatMap((item) =>
item.type === 'type' && item.required ? [item] : []
)
for (const prop of requiredProps) {
if (withDefaultsProps.includes(prop.propName)) {
const firstToken = context.getSourceCode().getFirstToken(prop.node)
// skip setter & getter case
if (firstToken.value === 'get' || firstToken.value === 'set') {
return
}
// skip computed
if (prop.node.computed) {
return
}
const keyToken = findKeyToken(
prop,
context.getSourceCode().getTokens(prop.node)
)
if (!keyToken) return
context.report({
node: prop.node,
loc: prop.node.loc,
data: {
key: prop.propName
},
message: `Prop "{{ key }}" should be optional.`,
fix: (fixer) => fixer.insertTextAfter(keyToken, '?')
})
}
}
}
})
}
}