From 043797204dc372f54a3e86a5c78517868b42047e Mon Sep 17 00:00:00 2001 From: Flo Edelmann Date: Fri, 29 Oct 2021 02:38:21 +0200 Subject: [PATCH] Support Nuxt.js's `asyncData` in various rules (#1679) * Support `asyncData` in `vue/no-undef-properties` * Support `asyncData` in `vue/no-dupe-keys` * Support `asyncData` in `vue/no-reserved-keys` * Support `asyncData` in `vue/no-template-shadow` * Support `asyncData` in `vue/no-unused-properties` * Lint --- lib/rules/no-dupe-keys.js | 9 ++++- lib/rules/no-reserved-keys.js | 14 ++++++-- lib/rules/no-template-shadow.js | 9 ++++- lib/rules/no-undef-properties.js | 5 ++- lib/rules/no-unused-properties.js | 6 +++- lib/utils/index.js | 2 +- tests/lib/rules/no-dupe-keys.js | 23 ++++++++++++ tests/lib/rules/no-reserved-keys.js | 36 +++++++++++++++++++ tests/lib/rules/no-template-shadow.js | 22 ++++++++++++ tests/lib/rules/no-undef-properties.js | 17 +++++++++ tests/lib/rules/no-unused-properties.js | 48 ++++++++++++++++++++++++- 11 files changed, 183 insertions(+), 8 deletions(-) diff --git a/lib/rules/no-dupe-keys.js b/lib/rules/no-dupe-keys.js index 8b5e8e54c..61ffda40e 100644 --- a/lib/rules/no-dupe-keys.js +++ b/lib/rules/no-dupe-keys.js @@ -14,7 +14,14 @@ const utils = require('../utils') // Rule Definition // ------------------------------------------------------------------------------ /** @type {GroupName[]} */ -const GROUP_NAMES = ['props', 'computed', 'data', 'methods', 'setup'] +const GROUP_NAMES = [ + 'props', + 'computed', + 'data', + 'asyncData', + 'methods', + 'setup' +] module.exports = { meta: { diff --git a/lib/rules/no-reserved-keys.js b/lib/rules/no-reserved-keys.js index 5b73d9c1f..ea684618f 100644 --- a/lib/rules/no-reserved-keys.js +++ b/lib/rules/no-reserved-keys.js @@ -16,7 +16,14 @@ const utils = require('../utils') const RESERVED_KEYS = require('../utils/vue-reserved.json') /** @type {GroupName[]} */ -const GROUP_NAMES = ['props', 'computed', 'data', 'methods', 'setup'] +const GROUP_NAMES = [ + 'props', + 'computed', + 'data', + 'asyncData', + 'methods', + 'setup' +] module.exports = { meta: { @@ -76,7 +83,10 @@ module.exports = { utils.executeOnVue(context, (obj) => { const properties = utils.iterateProperties(obj, groups) for (const o of properties) { - if (o.groupName === 'data' && o.name[0] === '_') { + if ( + (o.groupName === 'data' || o.groupName === 'asyncData') && + o.name[0] === '_' + ) { context.report({ node: o.node, messageId: 'startsWithUnderscore', diff --git a/lib/rules/no-template-shadow.js b/lib/rules/no-template-shadow.js index f66f8a701..e3e803792 100644 --- a/lib/rules/no-template-shadow.js +++ b/lib/rules/no-template-shadow.js @@ -19,7 +19,14 @@ const utils = require('../utils') // ------------------------------------------------------------------------------ /** @type {GroupName[]} */ -const GROUP_NAMES = ['props', 'computed', 'data', 'methods', 'setup'] +const GROUP_NAMES = [ + 'props', + 'computed', + 'data', + 'asyncData', + 'methods', + 'setup' +] module.exports = { meta: { diff --git a/lib/rules/no-undef-properties.js b/lib/rules/no-undef-properties.js index fdd506cc5..4246f771b 100644 --- a/lib/rules/no-undef-properties.js +++ b/lib/rules/no-undef-properties.js @@ -32,6 +32,7 @@ const { // ------------------------------------------------------------------------------ const GROUP_PROPERTY = 'props' +const GROUP_ASYNC_DATA = 'asyncData' // Nuxt.js const GROUP_DATA = 'data' const GROUP_COMPUTED_PROPERTY = 'computed' const GROUP_METHODS = 'methods' @@ -334,6 +335,7 @@ module.exports = { node, new Set([ GROUP_PROPERTY, + GROUP_ASYNC_DATA, GROUP_DATA, GROUP_COMPUTED_PROPERTY, GROUP_SETUP, @@ -342,7 +344,8 @@ module.exports = { ]) )) { const propertyMap = - prop.groupName === GROUP_DATA && + (prop.groupName === GROUP_DATA || + prop.groupName === GROUP_ASYNC_DATA) && prop.type === 'object' && prop.property.value.type === 'ObjectExpression' ? getObjectPropertyMap(prop.property.value) diff --git a/lib/rules/no-unused-properties.js b/lib/rules/no-unused-properties.js index 0a36c6579..74762e446 100644 --- a/lib/rules/no-unused-properties.js +++ b/lib/rules/no-unused-properties.js @@ -55,6 +55,7 @@ const { const GROUP_PROPERTY = 'props' const GROUP_DATA = 'data' +const GROUP_ASYNC_DATA = 'asyncData' const GROUP_COMPUTED_PROPERTY = 'computed' const GROUP_METHODS = 'methods' const GROUP_SETUP = 'setup' @@ -64,6 +65,7 @@ const GROUP_EXPOSE = 'expose' const PROPERTY_LABEL = { props: 'property', data: 'data', + asyncData: 'async data', computed: 'computed property', methods: 'method', setup: 'property returned from `setup()`', @@ -213,6 +215,7 @@ module.exports = { enum: [ GROUP_PROPERTY, GROUP_DATA, + GROUP_ASYNC_DATA, GROUP_COMPUTED_PROPERTY, GROUP_METHODS, GROUP_SETUP @@ -350,7 +353,8 @@ module.exports = { // used if ( deepData && - property.groupName === 'data' && + (property.groupName === 'data' || + property.groupName === 'asyncData') && property.type === 'object' ) { // Check the deep properties of the data option. diff --git a/lib/utils/index.js b/lib/utils/index.js index 5c49d15f2..ac94af2d1 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -23,7 +23,7 @@ * @typedef { {key: string | null, value: BlockStatement | null} } ComponentComputedProperty */ /** - * @typedef { 'props' | 'data' | 'computed' | 'setup' | 'watch' | 'methods' | 'provide' | 'inject' | 'expose' } GroupName + * @typedef { 'props' | 'asyncData' | 'data' | 'computed' | 'setup' | 'watch' | 'methods' | 'provide' | 'inject' | 'expose' } GroupName * @typedef { { type: 'array', name: string, groupName: GroupName, node: Literal | TemplateLiteral } } ComponentArrayPropertyData * @typedef { { type: 'object', name: string, groupName: GroupName, node: Identifier | Literal | TemplateLiteral, property: Property } } ComponentObjectPropertyData * @typedef { ComponentArrayPropertyData | ComponentObjectPropertyData } ComponentPropertyData diff --git a/tests/lib/rules/no-dupe-keys.js b/tests/lib/rules/no-dupe-keys.js index d85655669..9e01f0856 100644 --- a/tests/lib/rules/no-dupe-keys.js +++ b/tests/lib/rules/no-dupe-keys.js @@ -709,6 +709,29 @@ ruleTester.run('no-dupe-keys', rule, { } ] }, + { + filename: 'test.vue', + code: ` + export default { + asyncData() { + return { + foo: 1 + } + }, + data() { + return { + foo: 2 + } + }, + } + `, + errors: [ + { + message: "Duplicated key 'foo'.", + line: 10 + } + ] + }, { filename: 'test.js', code: ` diff --git a/tests/lib/rules/no-reserved-keys.js b/tests/lib/rules/no-reserved-keys.js index 02a1e79b9..b262ea44f 100644 --- a/tests/lib/rules/no-reserved-keys.js +++ b/tests/lib/rules/no-reserved-keys.js @@ -156,6 +156,25 @@ ruleTester.run('no-reserved-keys', rule, { } ] }, + { + filename: 'test.js', + code: ` + new Vue({ + asyncData () { + return { + $el: '' + } + } + }) + `, + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + message: "Key '$el' is reserved.", + line: 5 + } + ] + }, { filename: 'test.js', code: ` @@ -209,6 +228,23 @@ ruleTester.run('no-reserved-keys', rule, { } ] }, + { + filename: 'test.js', + code: ` + new Vue({ + asyncData: () => ({ + _foo: String + }) + }) + `, + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + message: "Keys starting with '_' are reserved in '_foo' group.", + line: 4 + } + ] + }, { filename: 'test.js', code: ` diff --git a/tests/lib/rules/no-template-shadow.js b/tests/lib/rules/no-template-shadow.js index 1f1daa184..cd66b06ab 100644 --- a/tests/lib/rules/no-template-shadow.js +++ b/tests/lib/rules/no-template-shadow.js @@ -250,6 +250,28 @@ ruleTester.run('no-template-shadow', rule, { } ] }, + { + filename: 'test.vue', + code: ` + `, + errors: [ + { + message: "Variable 'i' is already declared in the upper scope.", + type: 'Identifier', + line: 2 + } + ] + }, { filename: 'test.vue', code: `