diff --git a/lib/rules/no-arrow-functions-in-watch.js b/lib/rules/no-arrow-functions-in-watch.js index 77bb6787e..ca83a16a6 100644 --- a/lib/rules/no-arrow-functions-in-watch.js +++ b/lib/rules/no-arrow-functions-in-watch.js @@ -28,14 +28,18 @@ module.exports = { return } for (const property of watchValue.properties) { - if ( - property.type === 'Property' && - property.value.type === 'ArrowFunctionExpression' - ) { - context.report({ - node: property, - message: 'You should not use an arrow function to define a watcher.' - }) + if (property.type !== 'Property') { + continue + } + + for (const handler of utils.iterateWatchHandlerValues(property)) { + if (handler.type === 'ArrowFunctionExpression') { + context.report({ + node: handler, + message: + 'You should not use an arrow function to define a watcher.' + }) + } } } }) diff --git a/lib/rules/no-unused-properties.js b/lib/rules/no-unused-properties.js index 75b56a4ef..a405c8e60 100644 --- a/lib/rules/no-unused-properties.js +++ b/lib/rules/no-unused-properties.js @@ -634,24 +634,17 @@ module.exports = { if (watcher.type === 'object') { const property = watcher.property if (property.kind === 'init') { - /** @type {Expression | null} */ - let handlerValueNode = null - if (property.value.type === 'ObjectExpression') { - const handler = utils.findProperty(property.value, 'handler') - if (handler) { - handlerValueNode = handler.value - } - } else { - handlerValueNode = property.value - } - if ( - handlerValueNode && - (handlerValueNode.type === 'Literal' || - handlerValueNode.type === 'TemplateLiteral') - ) { - const name = utils.getStringLiteralValue(handlerValueNode) - if (name != null) { - watcherUsedProperties.add(name) + for (const handlerValueNode of utils.iterateWatchHandlerValues( + property + )) { + if ( + handlerValueNode.type === 'Literal' || + handlerValueNode.type === 'TemplateLiteral' + ) { + const name = utils.getStringLiteralValue(handlerValueNode) + if (name != null) { + watcherUsedProperties.add(name) + } } } } @@ -699,11 +692,11 @@ module.exports = { if ( utils.getStaticPropertyName(parentParentProperty) !== 'computed' || - utils.getStaticPropertyName(property) !== 'handler' + utils.getStaticPropertyName(property) !== 'get' ) { return } - // check { computed: { foo: { handler: (vm) => vm.prop } } } + // check { computed: { foo: { get: () => vm.prop } } } } else { return } diff --git a/lib/utils/index.js b/lib/utils/index.js index 793d34403..3df90418a 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -1476,6 +1476,13 @@ module.exports = { } }, + /** + * Return generator with the all handler nodes defined in the given watcher property. + * @param {Property|Expression} property + * @returns {IterableIterator} + */ + iterateWatchHandlerValues, + /** * Wraps composition API trace map in both 'vue' and '@vue/composition-api' imports * @param {import('eslint-utils').TYPES.TraceMap} map @@ -1990,3 +1997,26 @@ function getComponentComments(context) { componentComments.set(context, tokens) return tokens } + +/** + * Return generator with the all handler nodes defined in the given watcher property. + * @param {Property|Expression} property + * @returns {IterableIterator} + */ +function* iterateWatchHandlerValues(property) { + const value = property.type === 'Property' ? property.value : property + if (value.type === 'ObjectExpression') { + const handler = findProperty(value, 'handler') + if (handler) { + yield handler.value + } + } else if (value.type === 'ArrayExpression') { + for (const element of value.elements.filter(isDef)) { + if (element.type !== 'SpreadElement') { + yield* iterateWatchHandlerValues(element) + } + } + } else { + yield value + } +} diff --git a/tests/lib/rules/no-arrow-functions-in-watch.js b/tests/lib/rules/no-arrow-functions-in-watch.js index b98179a3b..0e137c193 100644 --- a/tests/lib/rules/no-arrow-functions-in-watch.js +++ b/tests/lib/rules/no-arrow-functions-in-watch.js @@ -218,6 +218,51 @@ ruleTester.run('no-arrow-functions-in-watch', rule, { line: 15 } ] + }, + { + filename: 'test.vue', + code: ` + export default { + watch: { + foo:{ + handler: function() {}, + }, + bar:{ + handler: () => {} + } + } + }`, + errors: [ + { + message: 'You should not use an arrow function to define a watcher.', + line: 8 + } + ] + }, + { + filename: 'test.vue', + code: ` + export default { + watch: { + e: [ + 'handle1', + (val, oldVal) => { /* ... */ }, + { + handler: (val, oldVal) => { /* ... */ }, + } + ], + } + }`, + errors: [ + { + message: 'You should not use an arrow function to define a watcher.', + line: 6 + }, + { + message: 'You should not use an arrow function to define a watcher.', + line: 8 + } + ] } ] }) diff --git a/tests/lib/rules/no-unused-properties.js b/tests/lib/rules/no-unused-properties.js index 78e15c4f8..1419add66 100644 --- a/tests/lib/rules/no-unused-properties.js +++ b/tests/lib/rules/no-unused-properties.js @@ -263,6 +263,29 @@ tester.run('no-unused-properties', rule, { ` }, + { + filename: 'test.vue', + code: ` + + `, + options: allOptions + }, // data used as a template identifier { @@ -1114,7 +1137,7 @@ tester.run('no-unused-properties', rule, { props: ['x'], computed: { y: { - handler: (vm) => vm.x * 2 + get: () => this.x * 2 } } };