From b130bafca00d2ebdf189a3eca5cffb31953e0cbd Mon Sep 17 00:00:00 2001 From: ota Date: Sat, 19 Sep 2020 11:43:00 +0900 Subject: [PATCH 1/2] Add `vue/no-deprecated-props-default-this` rule --- docs/rules/README.md | 1 + .../rules/no-deprecated-props-default-this.md | 70 +++++++ lib/configs/vue3-essential.js | 1 + lib/index.js | 1 + lib/rules/no-deprecated-props-default-this.js | 108 ++++++++++ .../rules/no-deprecated-props-default-this.js | 187 ++++++++++++++++++ 6 files changed, 368 insertions(+) create mode 100644 docs/rules/no-deprecated-props-default-this.md create mode 100644 lib/rules/no-deprecated-props-default-this.js create mode 100644 tests/lib/rules/no-deprecated-props-default-this.js diff --git a/docs/rules/README.md b/docs/rules/README.md index 9798e7778..1fafe81f5 100644 --- a/docs/rules/README.md +++ b/docs/rules/README.md @@ -50,6 +50,7 @@ Enforce all the rules in this category, as well as all higher priority rules, wi | [vue/no-deprecated-functional-template](./no-deprecated-functional-template.md) | disallow using deprecated the `functional` template (in Vue.js 3.0.0+) | | | [vue/no-deprecated-html-element-is](./no-deprecated-html-element-is.md) | disallow using deprecated the `is` attribute on HTML elements (in Vue.js 3.0.0+) | | | [vue/no-deprecated-inline-template](./no-deprecated-inline-template.md) | disallow using deprecated `inline-template` attribute (in Vue.js 3.0.0+) | | +| [vue/no-deprecated-props-default-this](./no-deprecated-props-default-this.md) | disallow props default function `this` access (in Vue.js 3.0.0+) | | | [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: | | [vue/no-deprecated-slot-scope-attribute](./no-deprecated-slot-scope-attribute.md) | disallow deprecated `slot-scope` attribute (in Vue.js 2.6.0+) | :wrench: | diff --git a/docs/rules/no-deprecated-props-default-this.md b/docs/rules/no-deprecated-props-default-this.md new file mode 100644 index 000000000..237027bc7 --- /dev/null +++ b/docs/rules/no-deprecated-props-default-this.md @@ -0,0 +1,70 @@ +--- +pageClass: rule-details +sidebarDepth: 0 +title: vue/no-deprecated-props-default-this +description: disallow props default function `this` access (in Vue.js 3.0.0+) +--- +# vue/no-deprecated-props-default-this +> disallow props default function `this` access (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"`. + +## :book: Rule Details + +This rule reports the use of `this` within the props default value factory functions. +In Vue.js 3.0.0+, props default value factory functions no longer have access to `this`. + +See [Migration Guide - Props Default Function `this` Access](https://v3.vuejs.org/guide/migration/props-default-this.html) for more details. + + + +```vue + +``` + + + + + +```vue + +``` + + + +## :wrench: Options + +Nothing. + +## :books: Further Reading + +- [Migration Guide - Props Default Function `this` Access](https://v3.vuejs.org/guide/migration/props-default-this.html) + +## :mag: Implementation + +- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-deprecated-props-default-this.js) +- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-deprecated-props-default-this.js) diff --git a/lib/configs/vue3-essential.js b/lib/configs/vue3-essential.js index 7d715c18a..d1e2d1768 100644 --- a/lib/configs/vue3-essential.js +++ b/lib/configs/vue3-essential.js @@ -18,6 +18,7 @@ module.exports = { 'vue/no-deprecated-functional-template': 'error', 'vue/no-deprecated-html-element-is': 'error', 'vue/no-deprecated-inline-template': 'error', + 'vue/no-deprecated-props-default-this': 'error', 'vue/no-deprecated-scope-attribute': 'error', 'vue/no-deprecated-slot-attribute': 'error', 'vue/no-deprecated-slot-scope-attribute': 'error', diff --git a/lib/index.js b/lib/index.js index 556fadeb4..df641f04b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -59,6 +59,7 @@ module.exports = { 'no-deprecated-functional-template': require('./rules/no-deprecated-functional-template'), 'no-deprecated-html-element-is': require('./rules/no-deprecated-html-element-is'), 'no-deprecated-inline-template': require('./rules/no-deprecated-inline-template'), + 'no-deprecated-props-default-this': require('./rules/no-deprecated-props-default-this'), 'no-deprecated-scope-attribute': require('./rules/no-deprecated-scope-attribute'), 'no-deprecated-slot-attribute': require('./rules/no-deprecated-slot-attribute'), 'no-deprecated-slot-scope-attribute': require('./rules/no-deprecated-slot-scope-attribute'), diff --git a/lib/rules/no-deprecated-props-default-this.js b/lib/rules/no-deprecated-props-default-this.js new file mode 100644 index 000000000..772914868 --- /dev/null +++ b/lib/rules/no-deprecated-props-default-this.js @@ -0,0 +1,108 @@ +/** + * @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 props default function `this` access (in Vue.js 3.0.0+)', + categories: ['vue3-essential'], + url: + 'https://eslint.vuejs.org/rules/no-deprecated-props-default-this.html' + }, + fixable: null, + schema: [], + messages: { + deprecated: + 'Props default value factory functions no longer have access to `this`.' + } + }, + /** @param {RuleContext} context */ + create(context) { + /** + * @typedef {object} ScopeStack + * @property {ScopeStack | null} upper + * @property {FunctionExpression | FunctionDeclaration} node + * @property {boolean} propDefault + */ + /** @type {Set} */ + const propsDefault = new Set() + /** @type {ScopeStack | null} */ + let scopeStack = null + + /** + * @param {FunctionExpression | FunctionDeclaration | ArrowFunctionExpression} node + */ + function onFunctionEnter(node) { + if (node.type === 'ArrowFunctionExpression') { + return + } + if (scopeStack) { + scopeStack = { + upper: scopeStack, + node, + propDefault: false + } + } else if (node.type === 'FunctionExpression' && propsDefault.has(node)) { + scopeStack = { + upper: scopeStack, + node, + propDefault: true + } + } + } + + /** + * @param {FunctionExpression | FunctionDeclaration | ArrowFunctionExpression} node + */ + function onFunctionExit(node) { + if (scopeStack && scopeStack.node === node) { + scopeStack = scopeStack.upper + } + } + return utils.defineVueVisitor(context, { + onVueObjectEnter(node) { + for (const prop of utils.getComponentProps(node)) { + if (prop.type !== 'object') { + continue + } + if (prop.value.type !== 'ObjectExpression') { + continue + } + const def = utils.findProperty(prop.value, 'default') + if (!def) { + continue + } + if (def.value.type !== 'FunctionExpression') { + continue + } + propsDefault.add(def.value) + } + }, + ':function': onFunctionEnter, + ':function:exit': onFunctionExit, + ThisExpression(node) { + if (scopeStack && scopeStack.propDefault) { + context.report({ + node, + messageId: 'deprecated' + }) + } + } + }) + } +} diff --git a/tests/lib/rules/no-deprecated-props-default-this.js b/tests/lib/rules/no-deprecated-props-default-this.js new file mode 100644 index 000000000..0993e817a --- /dev/null +++ b/tests/lib/rules/no-deprecated-props-default-this.js @@ -0,0 +1,187 @@ +/** + * @author Yosuke Ota + * See LICENSE file in root directory for full license. + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const rule = require('../../../lib/rules/no-deprecated-props-default-this') +const RuleTester = require('eslint').RuleTester + +// ------------------------------------------------------------------------------ +// Tests +// ------------------------------------------------------------------------------ + +const ruleTester = new RuleTester({ + parser: require.resolve('vue-eslint-parser'), + parserOptions: { ecmaVersion: 2020, sourceType: 'module' } +}) + +ruleTester.run('no-deprecated-props-default-this', rule, { + valid: [ + { + filename: 'test.vue', + code: ` + + + ` + }, + { + filename: 'test.vue', + code: ` + + + ` + }, + { + filename: 'test.vue', + code: ` + + + `, + errors: [{}, {}] + }, + { + filename: 'test.vue', + code: ` + + + ` + } + ], + + invalid: [ + { + filename: 'test.vue', + code: ` + + + `, + errors: [ + { + message: + 'Props default value factory functions no longer have access to `this`.', + line: 9, + column: 24, + endLine: 9, + endColumn: 28 + } + ] + }, + { + filename: 'test.vue', + code: ` + + + `, + errors: [ + { + message: + 'Props default value factory functions no longer have access to `this`.', + line: 9, + column: 30, + endLine: 9, + endColumn: 34 + } + ] + }, + { + filename: 'test.vue', + code: ` + + + `, + errors: [ + 'Props default value factory functions no longer have access to `this`.', + 'Props default value factory functions no longer have access to `this`.' + ] + } + ] +}) From 06985697f734a924fa9c914aa77e321b11729151 Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Tue, 22 Sep 2020 22:37:49 +0900 Subject: [PATCH 2/2] update comments --- docs/rules/README.md | 2 +- docs/rules/no-deprecated-props-default-this.md | 4 ++-- lib/rules/no-deprecated-props-default-this.js | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/rules/README.md b/docs/rules/README.md index 1fafe81f5..c0e7bc6a2 100644 --- a/docs/rules/README.md +++ b/docs/rules/README.md @@ -50,7 +50,7 @@ Enforce all the rules in this category, as well as all higher priority rules, wi | [vue/no-deprecated-functional-template](./no-deprecated-functional-template.md) | disallow using deprecated the `functional` template (in Vue.js 3.0.0+) | | | [vue/no-deprecated-html-element-is](./no-deprecated-html-element-is.md) | disallow using deprecated the `is` attribute on HTML elements (in Vue.js 3.0.0+) | | | [vue/no-deprecated-inline-template](./no-deprecated-inline-template.md) | disallow using deprecated `inline-template` attribute (in Vue.js 3.0.0+) | | -| [vue/no-deprecated-props-default-this](./no-deprecated-props-default-this.md) | disallow props default function `this` access (in Vue.js 3.0.0+) | | +| [vue/no-deprecated-props-default-this](./no-deprecated-props-default-this.md) | disallow props default function `this` access | | | [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: | | [vue/no-deprecated-slot-scope-attribute](./no-deprecated-slot-scope-attribute.md) | disallow deprecated `slot-scope` attribute (in Vue.js 2.6.0+) | :wrench: | diff --git a/docs/rules/no-deprecated-props-default-this.md b/docs/rules/no-deprecated-props-default-this.md index 237027bc7..51ae71013 100644 --- a/docs/rules/no-deprecated-props-default-this.md +++ b/docs/rules/no-deprecated-props-default-this.md @@ -2,10 +2,10 @@ pageClass: rule-details sidebarDepth: 0 title: vue/no-deprecated-props-default-this -description: disallow props default function `this` access (in Vue.js 3.0.0+) +description: disallow props default function `this` access --- # vue/no-deprecated-props-default-this -> disallow props default function `this` access (in Vue.js 3.0.0+) +> disallow props default function `this` access - :gear: This rule is included in all of `"plugin:vue/vue3-essential"`, `"plugin:vue/vue3-strongly-recommended"` and `"plugin:vue/vue3-recommended"`. diff --git a/lib/rules/no-deprecated-props-default-this.js b/lib/rules/no-deprecated-props-default-this.js index 772914868..926476c1e 100644 --- a/lib/rules/no-deprecated-props-default-this.js +++ b/lib/rules/no-deprecated-props-default-this.js @@ -18,8 +18,7 @@ module.exports = { meta: { type: 'problem', docs: { - description: - 'disallow props default function `this` access (in Vue.js 3.0.0+)', + description: 'disallow props default function `this` access', categories: ['vue3-essential'], url: 'https://eslint.vuejs.org/rules/no-deprecated-props-default-this.html'