Skip to content

Commit

Permalink
Fixed false negatives for props in template in `vue/no-unused-propert…
Browse files Browse the repository at this point in the history
…ies` (#2435)
  • Loading branch information
ItMaga committed Apr 14, 2024
1 parent a4be0fc commit e665b7c
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 6 deletions.
33 changes: 27 additions & 6 deletions lib/rules/no-unused-properties.js
Expand Up @@ -233,6 +233,8 @@ module.exports = {
const deepData = Boolean(options.deepData)
const ignorePublicMembers = Boolean(options.ignorePublicMembers)
const unreferencedOptions = new Set(options.unreferencedOptions || [])
/** @type {null | Pattern} */
let propsReferencePattern = null

const propertyReferenceExtractor = definePropertyReferenceExtractor(
context,
Expand Down Expand Up @@ -332,8 +334,9 @@ module.exports = {

for (const property of container.properties) {
if (
property.groupName === 'props' &&
propertyReferencesForProps.hasProperty(property.name)
(property.groupName === 'props' &&
propertyReferencesForProps.hasProperty(property.name)) ||
propertyReferences.hasProperty('$props')
) {
// used props
continue
Expand Down Expand Up @@ -369,6 +372,7 @@ module.exports = {
}
continue
}

context.report({
node: property.node,
messageId: 'unused',
Expand Down Expand Up @@ -450,9 +454,9 @@ module.exports = {
return
}

const pattern = target.parent.id
propsReferencePattern = target.parent.id
const propertyReferences =
propertyReferenceExtractor.extractFromPattern(pattern)
propertyReferenceExtractor.extractFromPattern(propsReferencePattern)
container.propertyReferencesForProps.push(propertyReferences)
},
onDefineModelEnter(node, model) {
Expand Down Expand Up @@ -709,9 +713,26 @@ module.exports = {
* @param {VExpressionContainer} node
*/
VExpressionContainer(node) {
templatePropertiesContainer.propertyReferences.push(
const property =
propertyReferenceExtractor.extractFromVExpressionContainer(node)
)

templatePropertiesContainer.propertyReferences.push(property)

if (!propsReferencePattern) {
return
}

// props.prop in template
for (const key of property.allProperties().keys()) {
if (
propsReferencePattern.type === 'Identifier' &&
propsReferencePattern.name === key
) {
templatePropertiesContainer.propertyReferences.push(
property.getNest(key)
)
}
}
},
/**
* @param {VAttribute} node
Expand Down
121 changes: 121 additions & 0 deletions tests/lib/rules/no-unused-properties.js
Expand Up @@ -718,6 +718,20 @@ tester.run('no-unused-properties', rule, {
</script>
`
},
// a property used as a template $props expression
{
filename: 'test.vue',
code: `
<template>
<div>{{ $props }}</div>
</template>
<script>
export default {
props: ['count']
}
</script>
`
},

// properties used in a template expression
{
Expand Down Expand Up @@ -910,6 +924,20 @@ tester.run('no-unused-properties', rule, {
</script>
`
},
// a property used in v-on as $props expression
{
filename: 'test.vue',
code: `
<template>
<button @click="alert($props)" />
</template>
<script>
export default {
props: ['count']
};
</script>
`
},

// data used in a script expression
{
Expand Down Expand Up @@ -2452,6 +2480,48 @@ tester.run('no-unused-properties', rule, {
{{ foo }}
</template>
`
},

// props.prop in template
{
filename: 'test.vue',
code: `
<template>
{{props}}
</template>
<script setup>
const props = defineProps(['a', 'b', 'c'])
</script>`
},
{
filename: 'test.vue',
code: `
<template>
{{props.a}}
</template>
<script setup>
const props = defineProps(['a'])
</script>`
},
{
filename: 'test.vue',
code: `
<template>
{{foo.a}}
</template>
<script setup>
const foo = defineProps(['a'])
</script>`
},
{
code: `
<script setup lang="ts">
const props = defineProps<{ foo: string, bar: string }>()
</script>
<template>
{{ props.foo }}{{ bar }}
</template>`,
...getTypeScriptFixtureTestOptions()
}
],
invalid: [
Expand Down Expand Up @@ -4619,6 +4689,57 @@ tester.run('no-unused-properties', rule, {
line: 6
}
]
},

// a property used as a template $props member expression
{
filename: 'test.vue',
code: `
<template>
<div>{{ $props.foo }}</div>
</template>
<script>
export default {
props: ['foo', 'bar']
}
</script>
`,
errors: ["'bar' of property found, but never used."]
},

// props.prop in template
{
filename: 'test.vue',
code: `
<template>
{{props.a}}
</template>
<script setup>
const props = defineProps(['a', 'b'])
</script>`,
errors: ["'b' of property found, but never used."]
},
{
filename: 'test.vue',
code: `
<template>
{{foo.a}}
</template>
<script setup>
const foo = defineProps(['a', 'b'])
</script>`,
errors: ["'b' of property found, but never used."]
},
{
code: `
<script setup lang="ts">
const props = defineProps<{ foo: string, bar: string, baz: string }>()
</script>
<template>
{{ props.foo }}{{ bar }}
</template>`,
errors: ["'baz' of property found, but never used."],
...getTypeScriptFixtureTestOptions()
}
]
})
Expand Down

0 comments on commit e665b7c

Please sign in to comment.