From 25623ea572b8194153e203e66ca1bc367b5435a3 Mon Sep 17 00:00:00 2001 From: yoyo930021 Date: Mon, 13 Apr 2020 21:08:46 +0800 Subject: [PATCH] New: Add `vue/no-deprecated-events-api` rule --- docs/rules/README.md | 1 + docs/rules/no-deprecated-events-api.md | 57 +++++++ lib/configs/vue3-essential.js | 1 + lib/index.js | 1 + lib/rules/no-deprecated-events-api.js | 57 +++++++ tests/lib/rules/no-deprecated-events-api.js | 161 ++++++++++++++++++++ 6 files changed, 278 insertions(+) create mode 100644 docs/rules/no-deprecated-events-api.md create mode 100644 lib/rules/no-deprecated-events-api.js create mode 100644 tests/lib/rules/no-deprecated-events-api.js diff --git a/docs/rules/README.md b/docs/rules/README.md index e184873e5..01ab5e706 100644 --- a/docs/rules/README.md +++ b/docs/rules/README.md @@ -39,6 +39,7 @@ Enforce all the rules in this category, as well as all higher priority rules, wi | Rule ID | Description | | |:--------|:------------|:---| | [vue/no-async-in-computed-properties](./no-async-in-computed-properties.md) | disallow asynchronous actions in computed properties | | +| [vue/no-deprecated-events-api](./no-deprecated-events-api.md) | disallow using deprecated events api | | | [vue/no-deprecated-filter](./no-deprecated-filter.md) | disallow using deprecated filters syntax | | | [vue/no-deprecated-scope-attribute](./no-deprecated-scope-attribute.md) | disallow deprecated `scope` attribute (in Vue.js 2.5.0+) | :wrench: | | [vue/no-deprecated-slot-attribute](./no-deprecated-slot-attribute.md) | disallow deprecated `slot` attribute (in Vue.js 2.6.0+) | :wrench: | diff --git a/docs/rules/no-deprecated-events-api.md b/docs/rules/no-deprecated-events-api.md new file mode 100644 index 000000000..e855a5a4f --- /dev/null +++ b/docs/rules/no-deprecated-events-api.md @@ -0,0 +1,57 @@ +--- +pageClass: rule-details +sidebarDepth: 0 +title: vue/no-deprecated-events-api +description: disallow using deprecated events api +--- +# vue/no-deprecated-events-api +> disallow using deprecated events api + +- :gear: This rule is included in all of `"plugin:vue/vue3-essential"`, `"plugin:vue/vue3-strongly-recommended"` and `"plugin:vue/vue3-recommended"`. + +## :book: Rule Details + +This rule reports use of deprecated `$on`, `$off` `$once` api. (in Vue.js 3.0.0+). + + + +```vue + +``` + + + +## :wrench: Options + +Nothing. + +## :books: Further reading + +- [RFC: events api change](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0020-events-api-change.md) + +## :mag: Implementation + +- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-deprecated-events-api.js) +- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-deprecated-events-api.js) diff --git a/lib/configs/vue3-essential.js b/lib/configs/vue3-essential.js index 3e45ddd2c..b132cf5c3 100644 --- a/lib/configs/vue3-essential.js +++ b/lib/configs/vue3-essential.js @@ -7,6 +7,7 @@ module.exports = { extends: require.resolve('./base'), rules: { 'vue/no-async-in-computed-properties': 'error', + 'vue/no-deprecated-events-api': 'error', 'vue/no-deprecated-filter': 'error', 'vue/no-deprecated-scope-attribute': 'error', 'vue/no-deprecated-slot-attribute': 'error', diff --git a/lib/index.js b/lib/index.js index 10e2e8766..f05d78b9a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -40,6 +40,7 @@ module.exports = { 'no-boolean-default': require('./rules/no-boolean-default'), 'no-confusing-v-for-v-if': require('./rules/no-confusing-v-for-v-if'), 'no-custom-modifiers-on-v-model': require('./rules/no-custom-modifiers-on-v-model'), + 'no-deprecated-events-api': require('./rules/no-deprecated-events-api'), 'no-deprecated-filter': require('./rules/no-deprecated-filter'), 'no-deprecated-scope-attribute': require('./rules/no-deprecated-scope-attribute'), 'no-deprecated-slot-attribute': require('./rules/no-deprecated-slot-attribute'), diff --git a/lib/rules/no-deprecated-events-api.js b/lib/rules/no-deprecated-events-api.js new file mode 100644 index 000000000..488b893d3 --- /dev/null +++ b/lib/rules/no-deprecated-events-api.js @@ -0,0 +1,57 @@ +/** + * @fileoverview disallow using deprecated events api + * @author yoyo930021 + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const utils = require('../utils') + +// ------------------------------------------------------------------------------ +// Rule Definition +// ------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: 'problem', + docs: { + description: 'disallow using deprecated events api', + categories: ['vue3-essential'], + url: 'https://eslint.vuejs.org/rules/no-deprecated-events-api.html' + }, + fixable: null, + schema: [], + messages: { + noDeprecatedEventsApi: 'The Events api `$on`, `$off` `$once` is deprecated. Using external library instead, for example mitt.' + } + }, + + create (context) { + const forbiddenNodes = [] + + return Object.assign( + { + 'CallExpression > MemberExpression > ThisExpression' (node) { + if (!['$on', '$off', '$once'].includes(node.parent.property.name)) return + forbiddenNodes.push(node.parent.parent) + } + }, + utils.executeOnVue(context, (obj) => { + forbiddenNodes.forEach(node => { + if ( + node.loc.start.line >= obj.loc.start.line && + node.loc.end.line <= obj.loc.end.line + ) { + context.report({ + node, + messageId: 'noDeprecatedEventsApi' + }) + } + }) + }) + ) + } +} diff --git a/tests/lib/rules/no-deprecated-events-api.js b/tests/lib/rules/no-deprecated-events-api.js new file mode 100644 index 000000000..59a6c685f --- /dev/null +++ b/tests/lib/rules/no-deprecated-events-api.js @@ -0,0 +1,161 @@ +/* eslint-disable eslint-plugin/consistent-output */ +/** + * @fileoverview disallow using deprecated events api + * @author yoyo930021 + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const rule = require('../../../lib/rules/no-deprecated-events-api') + +const RuleTester = require('eslint').RuleTester + +const parserOptions = { + ecmaVersion: 2018, + sourceType: 'module' +} + +// ------------------------------------------------------------------------------ +// Tests +// ------------------------------------------------------------------------------ + +const ruleTester = new RuleTester() +ruleTester.run('no-deprecated-events-api', rule, { + + valid: [ + { + filename: 'test.js', + code: ` + createApp({ + mounted () { + this.$emit('start') + } + }) + `, + parserOptions + }, + { + filename: 'test.js', + code: ` + createApp({ + methods: { + click () { + this.$emit('click') + } + } + }) + `, + parserOptions + }, + { + filename: 'test.js', + code: ` + const another = function () { + this.$on('start', args => { + console.log('start') + }) + } + + createApp({ + mounted () { + this.$emit('start') + } + }) + `, + parserOptions + }, + { + filename: 'test.js', + code: ` + app.component('some-comp', { + mounted () { + this.$emit('start') + } + }) + `, + parserOptions + }, + { + filename: 'test.vue', + code: ` + export default { + mounted () { + this.$emit('start') + } + } + `, + parserOptions + }, + { + filename: 'test.vue', + code: ` + import mitt from 'mitt' + const emitter = mitt() + + export default { + setup () { + emitter.on('foo', e => console.log('foo', e)) + emitter.emit('foo', { a: 'b' }) + emitter.off('foo', onFoo) + } + } + `, + parserOptions + } + ], + + invalid: [ + { + filename: 'test.js', + code: ` + app.component('some-comp', { + mounted () { + this.$on('start', function (args) { + console.log('start', args) + }) + } + }) + `, + parserOptions, + errors: [{ + message: 'The Events api `$on`, `$off` `$once` is deprecated. Using external library instead, for example mitt.', + line: 4 + }] + }, + { + filename: 'test.js', + code: ` + app.component('some-comp', { + mounted () { + this.$off('start') + } + }) + `, + parserOptions, + errors: [{ + message: 'The Events api `$on`, `$off` `$once` is deprecated. Using external library instead, for example mitt.', + line: 4 + }] + }, + { + filename: 'test.vue', + code: ` + export default { + mounted () { + this.$once('start', function () { + console.log('start') + }) + } + } + `, + parserOptions, + errors: [{ + message: 'The Events api `$on`, `$off` `$once` is deprecated. Using external library instead, for example mitt.', + line: 4 + }] + } + ] +})