Skip to content

Commit

Permalink
Fixed false positives when used via argument in `vue/no-unused-proper…
Browse files Browse the repository at this point in the history
…ties` (#1324)
  • Loading branch information
ota-meshi committed Oct 18, 2020
1 parent d44fb18 commit 30da121
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 9 deletions.
100 changes: 91 additions & 9 deletions lib/rules/no-unused-properties.js
Expand Up @@ -578,6 +578,41 @@ module.exports = {
}
}

/**
* @param {VueComponentPropertiesContainer} container
* @param {UsedProps} baseUseProps
*/
function processUsed(container, baseUseProps) {
for (const { usedNames, unknown } of iterateUsedProps(baseUseProps)) {
if (unknown) {
container.unknown = true
return
}
for (const name of usedNames.names()) {
container.usedNames.add(name)
}
}
}

/**
* @param {Expression} node
* @returns {Property|null}
*/
function getParentProperty(node) {
if (
!node.parent ||
node.parent.type !== 'Property' ||
node.parent.value !== node
) {
return null
}
const property = node.parent
if (!property.parent || property.parent.type !== 'ObjectExpression') {
return null
}
return /** @type {Property} */ (property)
}

const scriptVisitor = Object.assign(
{},
utils.defineVueVisitor(context, {
Expand Down Expand Up @@ -629,6 +664,61 @@ module.exports = {
container.properties.push(prop)
}
},
/** @param { (FunctionExpression | ArrowFunctionExpression) & { parent: Property }} node */
'ObjectExpression > Property > :function[params.length>0]'(
node,
vueData
) {
const property = getParentProperty(node)
if (!property) {
return
}
if (property.parent === vueData.node) {
if (utils.getStaticPropertyName(property) !== 'data') {
return
}
// check { data: (vm) => vm.prop }
} else {
const parentProperty = getParentProperty(property.parent)
if (!parentProperty) {
return
}
if (parentProperty.parent === vueData.node) {
if (utils.getStaticPropertyName(parentProperty) !== 'computed') {
return
}
// check { computed: { foo: (vm) => vm.prop } }
} else {
const parentParentProperty = getParentProperty(
parentProperty.parent
)
if (!parentParentProperty) {
return
}
if (parentParentProperty.parent === vueData.node) {
if (
utils.getStaticPropertyName(parentParentProperty) !==
'computed' ||
utils.getStaticPropertyName(property) !== 'handler'
) {
return
}
// check { computed: { foo: { handler: (vm) => vm.prop } } }
} else {
return
}
}
}

const paramsUsedProps = getParamsUsedProps(node)
const usedProps = /** @type {ParamUsedProps} */ (paramsUsedProps.getParam(
0
))
processUsed(
getVueComponentPropertiesContainer(vueData.node),
usedProps
)
},
onSetupFunctionEnter(node, vueData) {
const container = getVueComponentPropertiesContainer(vueData.node)
if (node.params[0]) {
Expand Down Expand Up @@ -690,15 +780,7 @@ module.exports = {
const container = getVueComponentPropertiesContainer(vueData.node)
const usedProps = extractPatternOrThisProperties(node, context)

for (const { usedNames, unknown } of iterateUsedProps(usedProps)) {
if (unknown) {
container.unknown = true
return
}
for (const name of usedNames.names()) {
container.usedNames.add(name)
}
}
processUsed(container, usedProps)
}
}),
{
Expand Down
89 changes: 89 additions & 0 deletions tests/lib/rules/no-unused-properties.js
Expand Up @@ -1078,6 +1078,48 @@ tester.run('no-unused-properties', rule, {
</script>
`,
options: [{ groups: ['props', 'data'] }]
},
// contexts
{
filename: 'test.vue',
code: `
<script>
export default {
props: ['x'],
data: ({ x }) => ({
y: x
})
};
</script>
`
},
{
filename: 'test.vue',
code: `
<script>
export default {
props: ['x'],
computed: {
y: (vm) => vm.x * 2
}
};
</script>
`
},
{
filename: 'test.vue',
code: `
<script>
export default {
props: ['x'],
computed: {
y: {
handler: (vm) => vm.x * 2
}
}
};
</script>
`
}
],

Expand Down Expand Up @@ -1574,6 +1616,53 @@ tester.run('no-unused-properties', rule, {
})
`,
errors: ["'foo' of property found, but never used."]
},

// contexts
{
filename: 'test.vue',
code: `
<script>
export default {
props: ['x'],
data: () => ({
y: x
})
};
</script>
`,
errors: ["'x' of property found, but never used."]
},
{
filename: 'test.vue',
code: `
<script>
export default {
props: ['x'],
computed: {
[(vm) => vm.x * 2]: y
}
};
</script>
`,
errors: ["'x' of property found, but never used."]
},
{
filename: 'test.vue',
code: `
<script>
export default {
props: ['x'],
computed: {
y: {
handler: (vm) => vm.z * 2,
deep: (vm) => vm.x * 2
}
}
};
</script>
`,
errors: ["'x' of property found, but never used."]
}
]
})

0 comments on commit 30da121

Please sign in to comment.