Skip to content

Commit 88d8d1b

Browse files
authored
Update vue/no-unused-properties rule to support expose (#1566)
1 parent 5bbc3fe commit 88d8d1b

File tree

4 files changed

+113
-42
lines changed

4 files changed

+113
-42
lines changed

lib/rules/no-invalid-model-keys.js

-4
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@
66

77
const utils = require('../utils')
88

9-
/**
10-
* @typedef {import('../utils').GroupName} GroupName
11-
*/
12-
139
// ------------------------------------------------------------------------------
1410
// Rule Definition
1511
// ------------------------------------------------------------------------------

lib/rules/no-unused-properties.js

+49-37
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,20 @@ const GROUP_COMPUTED_PROPERTY = 'computed'
5353
const GROUP_METHODS = 'methods'
5454
const GROUP_SETUP = 'setup'
5555
const GROUP_WATCHER = 'watch'
56+
const GROUP_EXPOSE = 'expose'
5657

5758
const PROPERTY_LABEL = {
5859
props: 'property',
5960
data: 'data',
6061
computed: 'computed property',
6162
methods: 'method',
6263
setup: 'property returned from `setup()`',
63-
watch: 'watch'
64+
65+
// not use
66+
watch: 'watch',
67+
provide: 'provide',
68+
inject: 'inject',
69+
expose: 'expose'
6470
}
6571

6672
// ------------------------------------------------------------------------------
@@ -900,51 +906,57 @@ module.exports = {
900906
onVueObjectEnter(node) {
901907
const container = getVueComponentPropertiesContainer(node)
902908

903-
for (const watcher of utils.iterateProperties(
909+
for (const watcherOrExpose of utils.iterateProperties(
904910
node,
905-
new Set([GROUP_WATCHER])
911+
new Set([GROUP_WATCHER, GROUP_EXPOSE])
906912
)) {
907-
// Process `watch: { foo /* <- this */ () {} }`
908-
const segments = watcher.name.split('.')
909-
container.usedProperties.addUsed(segments[0], (context) => {
910-
return buildChainTracker(segments)(context)
911-
/**
912-
* @param {string[]} baseSegments
913-
* @returns {UsedPropertiesTracker}
914-
*/
915-
function buildChainTracker(baseSegments) {
916-
return () => {
917-
const subSegments = baseSegments.slice(1)
918-
const usedProps = new UsedProperties()
919-
if (subSegments.length) {
920-
usedProps.addUsed(
921-
subSegments[0],
922-
buildChainTracker(subSegments)
923-
)
913+
if (watcherOrExpose.groupName === GROUP_WATCHER) {
914+
const watcher = watcherOrExpose
915+
// Process `watch: { foo /* <- this */ () {} }`
916+
const segments = watcher.name.split('.')
917+
container.usedProperties.addUsed(segments[0], (context) => {
918+
return buildChainTracker(segments)(context)
919+
/**
920+
* @param {string[]} baseSegments
921+
* @returns {UsedPropertiesTracker}
922+
*/
923+
function buildChainTracker(baseSegments) {
924+
return () => {
925+
const subSegments = baseSegments.slice(1)
926+
const usedProps = new UsedProperties()
927+
if (subSegments.length) {
928+
usedProps.addUsed(
929+
subSegments[0],
930+
buildChainTracker(subSegments)
931+
)
932+
}
933+
return usedProps
924934
}
925-
return usedProps
926935
}
927-
}
928-
})
936+
})
929937

930-
// Process `watch: { x: 'foo' /* <- this */ }`
931-
if (watcher.type === 'object') {
932-
const property = watcher.property
933-
if (property.kind === 'init') {
934-
for (const handlerValueNode of utils.iterateWatchHandlerValues(
935-
property
936-
)) {
937-
if (
938-
handlerValueNode.type === 'Literal' ||
939-
handlerValueNode.type === 'TemplateLiteral'
940-
) {
941-
const name = utils.getStringLiteralValue(handlerValueNode)
942-
if (name != null) {
943-
container.usedProperties.addUsed(name, null)
938+
// Process `watch: { x: 'foo' /* <- this */ }`
939+
if (watcher.type === 'object') {
940+
const property = watcher.property
941+
if (property.kind === 'init') {
942+
for (const handlerValueNode of utils.iterateWatchHandlerValues(
943+
property
944+
)) {
945+
if (
946+
handlerValueNode.type === 'Literal' ||
947+
handlerValueNode.type === 'TemplateLiteral'
948+
) {
949+
const name = utils.getStringLiteralValue(handlerValueNode)
950+
if (name != null) {
951+
container.usedProperties.addUsed(name, null)
952+
}
944953
}
945954
}
946955
}
947956
}
957+
} else if (watcherOrExpose.groupName === GROUP_EXPOSE) {
958+
const expose = watcherOrExpose
959+
container.usedProperties.addUsed(expose.name, null)
948960
}
949961
}
950962
container.properties.push(...utils.iterateProperties(node, groups))

lib/utils/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
* @typedef { {key: string | null, value: BlockStatement | null} } ComponentComputedProperty
2424
*/
2525
/**
26-
* @typedef { 'props' | 'data' | 'computed' | 'setup' | 'watch' | 'methods' } GroupName
26+
* @typedef { 'props' | 'data' | 'computed' | 'setup' | 'watch' | 'methods' | 'provide' | 'inject' | 'expose' } GroupName
2727
* @typedef { { type: 'array', name: string, groupName: GroupName, node: Literal | TemplateLiteral } } ComponentArrayPropertyData
2828
* @typedef { { type: 'object', name: string, groupName: GroupName, node: Identifier | Literal | TemplateLiteral, property: Property } } ComponentObjectPropertyData
2929
* @typedef { ComponentArrayPropertyData | ComponentObjectPropertyData } ComponentPropertyData

tests/lib/rules/no-unused-properties.js

+63
Original file line numberDiff line numberDiff line change
@@ -1535,6 +1535,33 @@ tester.run('no-unused-properties', rule, {
15351535
ignorePublicMembers: true
15361536
}
15371537
]
1538+
},
1539+
1540+
// expose
1541+
{
1542+
filename: 'test.vue',
1543+
code: `
1544+
<template>
1545+
{{a}}
1546+
</template>
1547+
<script>
1548+
export default {
1549+
expose: ['a', 'b', 'c', 'd'],
1550+
props: ['a'],
1551+
data() {
1552+
return {
1553+
b: 42,
1554+
}
1555+
},
1556+
computed:{
1557+
c() {},
1558+
},
1559+
methods:{
1560+
d() {},
1561+
}
1562+
}
1563+
</script>`,
1564+
options: allOptions
15381565
}
15391566
],
15401567

@@ -2412,6 +2439,42 @@ tester.run('no-unused-properties', rule, {
24122439
props.b
24132440
</script>`,
24142441
errors: ["'c' of property found, but never used."]
2442+
},
2443+
2444+
// expose
2445+
{
2446+
filename: 'test.vue',
2447+
code: `
2448+
<template>
2449+
{{a}}
2450+
</template>
2451+
<script>
2452+
export default {
2453+
expose: ['a', 'c', 'e', 'g'],
2454+
props: ['a', 'b'],
2455+
data() {
2456+
return {
2457+
c: 42,
2458+
d: 42
2459+
}
2460+
},
2461+
computed:{
2462+
e() {},
2463+
f() {}
2464+
},
2465+
methods:{
2466+
g() {},
2467+
h() {}
2468+
}
2469+
}
2470+
</script>`,
2471+
options: allOptions,
2472+
errors: [
2473+
"'b' of property found, but never used.",
2474+
"'d' of data found, but never used.",
2475+
"'f' of computed property found, but never used.",
2476+
"'h' of method found, but never used."
2477+
]
24152478
}
24162479
]
24172480
})

0 commit comments

Comments
 (0)