From fb1fb7946a338173908471a2e4be4dab4c403568 Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Fri, 5 Jun 2020 11:13:16 +0900 Subject: [PATCH] Add `vue/no-deprecated-dollar-scopedslots-api` rule. (#1177) --- docs/rules/README.md | 1 + .../no-deprecated-dollar-scopedslots-api.md | 47 +++ lib/configs/vue3-essential.js | 1 + lib/index.js | 1 + .../no-deprecated-dollar-scopedslots-api.js | 79 +++++ .../no-deprecated-dollar-scopedslots-api.js | 288 ++++++++++++++++++ 6 files changed, 417 insertions(+) create mode 100644 docs/rules/no-deprecated-dollar-scopedslots-api.md create mode 100644 lib/rules/no-deprecated-dollar-scopedslots-api.js create mode 100644 tests/lib/rules/no-deprecated-dollar-scopedslots-api.js diff --git a/docs/rules/README.md b/docs/rules/README.md index 8d3e9fb32..40548ec13 100644 --- a/docs/rules/README.md +++ b/docs/rules/README.md @@ -43,6 +43,7 @@ Enforce all the rules in this category, as well as all higher priority rules, wi | [vue/no-async-in-computed-properties](./no-async-in-computed-properties.md) | disallow asynchronous actions in computed properties | | | [vue/no-deprecated-data-object-declaration](./no-deprecated-data-object-declaration.md) | disallow using deprecated object declaration on data (in Vue.js 3.0.0+) | :wrench: | | [vue/no-deprecated-dollar-listeners-api](./no-deprecated-dollar-listeners-api.md) | disallow using deprecated `$listeners` (in Vue.js 3.0.0+) | | +| [vue/no-deprecated-dollar-scopedslots-api](./no-deprecated-dollar-scopedslots-api.md) | disallow using deprecated `$scopedSlots` (in Vue.js 3.0.0+) | :wrench: | | [vue/no-deprecated-events-api](./no-deprecated-events-api.md) | disallow using deprecated events api (in Vue.js 3.0.0+) | | | [vue/no-deprecated-filter](./no-deprecated-filter.md) | disallow using deprecated filters syntax (in Vue.js 3.0.0+) | | | [vue/no-deprecated-functional-template](./no-deprecated-functional-template.md) | disallow using deprecated the `functional` template (in Vue.js 3.0.0+) | | diff --git a/docs/rules/no-deprecated-dollar-scopedslots-api.md b/docs/rules/no-deprecated-dollar-scopedslots-api.md new file mode 100644 index 000000000..9b1d577c7 --- /dev/null +++ b/docs/rules/no-deprecated-dollar-scopedslots-api.md @@ -0,0 +1,47 @@ +--- +pageClass: rule-details +sidebarDepth: 0 +title: vue/no-deprecated-dollar-scopedslots-api +description: disallow using deprecated `$scopedSlots` (in Vue.js 3.0.0+) +--- +# vue/no-deprecated-dollar-scopedslots-api +> disallow using deprecated `$scopedSlots` (in Vue.js 3.0.0+) + +- :gear: This rule is included in all of `"plugin:vue/vue3-essential"`, `"plugin:vue/vue3-strongly-recommended"` and `"plugin:vue/vue3-recommended"`. +- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule. + +## :book: Rule Details + +This rule reports use of deprecated `$scopedSlots`. (in Vue.js 3.0.0+). + + + +```vue + + +``` + + + +## :wrench: Options + +Nothing. + +## :books: Further reading + +- [Vue RFCs - 0006-slots-unification](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0006-slots-unification.md) + +## :mag: Implementation + +- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-deprecated-dollar-scopedslots-api.js) +- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-deprecated-dollar-scopedslots-api.js) diff --git a/lib/configs/vue3-essential.js b/lib/configs/vue3-essential.js index b2aec42d8..0e3e02f74 100644 --- a/lib/configs/vue3-essential.js +++ b/lib/configs/vue3-essential.js @@ -11,6 +11,7 @@ module.exports = { 'vue/no-async-in-computed-properties': 'error', 'vue/no-deprecated-data-object-declaration': 'error', 'vue/no-deprecated-dollar-listeners-api': 'error', + 'vue/no-deprecated-dollar-scopedslots-api': 'error', 'vue/no-deprecated-events-api': 'error', 'vue/no-deprecated-filter': 'error', 'vue/no-deprecated-functional-template': 'error', diff --git a/lib/index.js b/lib/index.js index d5fc21229..6eb4dc340 100644 --- a/lib/index.js +++ b/lib/index.js @@ -50,6 +50,7 @@ module.exports = { 'no-custom-modifiers-on-v-model': require('./rules/no-custom-modifiers-on-v-model'), 'no-deprecated-data-object-declaration': require('./rules/no-deprecated-data-object-declaration'), 'no-deprecated-dollar-listeners-api': require('./rules/no-deprecated-dollar-listeners-api'), + 'no-deprecated-dollar-scopedslots-api': require('./rules/no-deprecated-dollar-scopedslots-api'), 'no-deprecated-events-api': require('./rules/no-deprecated-events-api'), 'no-deprecated-filter': require('./rules/no-deprecated-filter'), 'no-deprecated-functional-template': require('./rules/no-deprecated-functional-template'), diff --git a/lib/rules/no-deprecated-dollar-scopedslots-api.js b/lib/rules/no-deprecated-dollar-scopedslots-api.js new file mode 100644 index 000000000..f369c70ff --- /dev/null +++ b/lib/rules/no-deprecated-dollar-scopedslots-api.js @@ -0,0 +1,79 @@ +/** + * @author Yosuke Ota + * See LICENSE file in root directory for full license. + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const utils = require('../utils') + +// ------------------------------------------------------------------------------ +// Rule Definition +// ------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: 'problem', + docs: { + description: + 'disallow using deprecated `$scopedSlots` (in Vue.js 3.0.0+)', + categories: ['vue3-essential'], + url: + 'https://eslint.vuejs.org/rules/no-deprecated-dollar-scopedslots-api.html' + }, + fixable: 'code', + schema: [], + messages: { + deprecated: 'The `$scopedSlots` is deprecated.' + } + }, + + create(context) { + return utils.defineTemplateBodyVisitor( + context, + { + VExpressionContainer(node) { + for (const reference of node.references) { + if (reference.variable != null) { + // Not vm reference + continue + } + if (reference.id.name === '$scopedSlots') { + context.report({ + node: reference.id, + messageId: 'deprecated', + fix(fixer) { + return fixer.replaceText(reference.id, '$slots') + } + }) + } + } + } + }, + utils.defineVueVisitor(context, { + MemberExpression(node) { + if ( + node.property.type !== 'Identifier' || + node.property.name !== '$scopedSlots' + ) { + return + } + if (!utils.isThis(node.object, context)) { + return + } + + context.report({ + node: node.property, + messageId: 'deprecated', + fix(fixer) { + return fixer.replaceText(node.property, '$slots') + } + }) + } + }) + ) + } +} diff --git a/tests/lib/rules/no-deprecated-dollar-scopedslots-api.js b/tests/lib/rules/no-deprecated-dollar-scopedslots-api.js new file mode 100644 index 000000000..303e5de99 --- /dev/null +++ b/tests/lib/rules/no-deprecated-dollar-scopedslots-api.js @@ -0,0 +1,288 @@ +/** + * @author Yosuke Ota + * See LICENSE file in root directory for full license. + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const rule = require('../../../lib/rules/no-deprecated-dollar-scopedslots-api') + +const RuleTester = require('eslint').RuleTester + +// ------------------------------------------------------------------------------ +// Tests +// ------------------------------------------------------------------------------ + +const ruleTester = new RuleTester({ + parser: require.resolve('vue-eslint-parser'), + parserOptions: { ecmaVersion: 2018, sourceType: 'module' } +}) +ruleTester.run('no-deprecated-dollar-scopedslots-api', rule, { + valid: [ + { + filename: 'test.vue', + code: ` + + + ` + }, + { + filename: 'test.vue', + code: ` + + ` + }, + { + filename: 'test.vue', + code: ` + + ` + }, + { + filename: 'test.vue', + code: ` + + ` + }, + { + filename: 'test.vue', + code: ` + + + ` + }, + { + filename: 'test.vue', + code: ` + + ` + } + ], + + invalid: [ + { + filename: 'test.vue', + code: ` + + + `, + output: ` + + + `, + errors: [ + { + line: 3, + column: 22, + messageId: 'deprecated', + endLine: 3, + endColumn: 34 + }, + { + line: 8, + column: 25, + messageId: 'deprecated', + endLine: 8, + endColumn: 37 + } + ] + }, + { + filename: 'test.vue', + code: ` + + + `, + output: ` + + + `, + errors: [ + { + line: 3, + column: 31, + messageId: 'deprecated', + endLine: 3, + endColumn: 43 + }, + { + line: 4, + column: 22, + messageId: 'deprecated', + endLine: 4, + endColumn: 34 + }, + { + line: 10, + column: 23, + messageId: 'deprecated', + endLine: 10, + endColumn: 35 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + output: ` + + `, + errors: [ + { + line: 6, + column: 23, + messageId: 'deprecated' + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + output: ` + + `, + errors: [ + { + line: 7, + column: 25, + messageId: 'deprecated' + } + ] + } + ] +})