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: `
diff --git a/tests/lib/rules/no-undef-properties.js b/tests/lib/rules/no-undef-properties.js
index 09e16bda9..f432a8d0e 100644
--- a/tests/lib/rules/no-undef-properties.js
+++ b/tests/lib/rules/no-undef-properties.js
@@ -67,6 +67,23 @@ tester.run('no-undef-properties', rule, {
`
},
+ {
+ filename: 'test.vue',
+ code: `
+
+ {{ foo }}
+
+
+ `
+ },
//default ignores
{
filename: 'test.vue',
diff --git a/tests/lib/rules/no-unused-properties.js b/tests/lib/rules/no-unused-properties.js
index de535bd25..ecd41243e 100644
--- a/tests/lib/rules/no-unused-properties.js
+++ b/tests/lib/rules/no-unused-properties.js
@@ -16,7 +16,7 @@ const tester = new RuleTester({
})
const allOptions = [
- { groups: ['props', 'computed', 'data', 'methods', 'setup'] }
+ { groups: ['props', 'computed', 'data', 'asyncData', 'methods', 'setup'] }
]
const deepDataOptions = [{ groups: ['data'], deepData: true }]
@@ -647,6 +647,26 @@ tester.run('no-unused-properties', rule, {
options: allOptions
},
+ // async data passed in a component
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+
+ `,
+ options: allOptions
+ },
+
// ignores unused data when marked with eslint-disable
{
filename: 'test.vue',
@@ -1709,6 +1729,32 @@ tester.run('no-unused-properties', rule, {
]
},
+ // unused async data
+ {
+ filename: 'test.vue',
+ code: `
+
+ {{ cont }}
+
+
+ `,
+ options: [{ groups: ['props', 'computed', 'data', 'asyncData'] }],
+ errors: [
+ {
+ message: "'count' of async data found, but never used.",
+ line: 9
+ }
+ ]
+ },
+
// unused computed property
{
filename: 'test.vue',