Skip to content

Commit

Permalink
Update vue/require-prop-type-constructor rule to support `<script s…
Browse files Browse the repository at this point in the history
…etup>` (#1536)

* Update `vue/require-prop-type-constructor` rule to support `<script setup>`

* fix tsc error
  • Loading branch information
ota-meshi committed Jul 2, 2021
1 parent 3262d93 commit 774056c
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 36 deletions.
24 changes: 21 additions & 3 deletions lib/rules/require-prop-type-constructor.js
Expand Up @@ -7,6 +7,12 @@
const utils = require('../utils')
const { isDef } = require('../utils')

/**
* @typedef {import('../utils').ComponentArrayProp} ComponentArrayProp
* @typedef {import('../utils').ComponentObjectProp} ComponentObjectProp
* @typedef {import('../utils').ComponentTypeProp} ComponentTypeProp
*/

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
Expand Down Expand Up @@ -76,8 +82,9 @@ module.exports = {
)
}

return utils.executeOnVueComponent(context, (obj) => {
for (const prop of utils.getComponentProps(obj)) {
/** @param {(ComponentArrayProp | ComponentObjectProp | ComponentTypeProp)[]} props */
function verifyProps(props) {
for (const prop of props) {
if (!prop.value || prop.propName == null) {
continue
}
Expand All @@ -94,6 +101,17 @@ module.exports = {
checkPropertyNode(prop.propName, typeProperty.value)
}
}
})
}

return utils.compositingVisitors(
utils.defineScriptSetupVisitor(context, {
onDefinePropsEnter(_node, props) {
verifyProps(props)
}
}),
utils.executeOnVueComponent(context, (obj) => {
verifyProps(utils.getComponentProps(obj))
})
)
}
}
67 changes: 34 additions & 33 deletions lib/utils/index.js
Expand Up @@ -1103,42 +1103,43 @@ module.exports = {
return null
}

const definePropsMap = new Map()
/**
* @param {CallExpression} node
*/
scriptSetupVisitor.CallExpression = (node) => {
if (
inScriptSetup(node) &&
node.callee.type === 'Identifier' &&
node.callee.name === 'defineProps'
) {
/** @type {(ComponentArrayProp | ComponentObjectProp | ComponentTypeProp)[]} */
let props = []
if (node.arguments.length >= 1) {
const defNode = getObjectOrArray(node.arguments[0])
if (defNode) {
props = getComponentPropsFromDefine(defNode)
}
} else if (
node.typeParameters &&
node.typeParameters.params.length >= 1
if (visitor.onDefinePropsEnter || visitor.onDefinePropsExit) {
const definePropsMap = new Map()
/**
* @param {CallExpression} node
*/
scriptSetupVisitor.CallExpression = (node) => {
if (
inScriptSetup(node) &&
node.callee.type === 'Identifier' &&
node.callee.name === 'defineProps'
) {
props = getComponentPropsFromTypeDefine(
context,
node.typeParameters.params[0]
)
/** @type {(ComponentArrayProp | ComponentObjectProp | ComponentTypeProp)[]} */
let props = []
if (node.arguments.length >= 1) {
const defNode = getObjectOrArray(node.arguments[0])
if (defNode) {
props = getComponentPropsFromDefine(defNode)
}
} else if (
node.typeParameters &&
node.typeParameters.params.length >= 1
) {
props = getComponentPropsFromTypeDefine(
context,
node.typeParameters.params[0]
)
}
callVisitor('onDefinePropsEnter', node, props)
}
definePropsMap.set(node, props)
callVisitor('onDefinePropsEnter', node, props)
callVisitor('CallExpression', node)
}
callVisitor('CallExpression', node)
}
scriptSetupVisitor['CallExpression:exit'] = (node) => {
callVisitor('CallExpression:exit', node)
if (definePropsMap.has(node)) {
callVisitor('onDefinePropsExit', node, definePropsMap.get(node))
definePropsMap.delete(node)
scriptSetupVisitor['CallExpression:exit'] = (node) => {
callVisitor('CallExpression:exit', node)
if (definePropsMap.has(node)) {
callVisitor('onDefinePropsExit', node, definePropsMap.get(node))
definePropsMap.delete(node)
}
}
}

Expand Down
30 changes: 30 additions & 0 deletions tests/lib/rules/require-prop-type-constructor.js
Expand Up @@ -355,6 +355,36 @@ ruleTester.run('require-prop-type-constructor', rule, {
line: 18
}
]
},
{
filename: 'SomeComponent.vue',
code: `
<script setup>
defineProps({
a: {
type: 'String',
default: 'abc'
},
})
</script>
`,
output: `
<script setup>
defineProps({
a: {
type: String,
default: 'abc'
},
})
</script>
`,
parser: require.resolve('vue-eslint-parser'),
errors: [
{
message: 'The "a" property should be a constructor.',
line: 5
}
]
}
]
})

0 comments on commit 774056c

Please sign in to comment.