diff --git a/docs/rules/next-tick-style.md b/docs/rules/next-tick-style.md
index 1224e93b9..c9e0fe5ef 100644
--- a/docs/rules/next-tick-style.md
+++ b/docs/rules/next-tick-style.md
@@ -2,13 +2,13 @@
pageClass: rule-details
sidebarDepth: 0
title: vue/next-tick-style
-description: enforce Promise or callback style in `nextTick`
+description: enforce Promise, Await or callback style in `nextTick`
since: v7.5.0
---
# vue/next-tick-style
-> enforce Promise or callback style in `nextTick`
+> enforce Promise, Await or callback style in `nextTick`
- :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.
@@ -52,13 +52,45 @@ Default is set to `promise`.
```json
{
- "vue/next-tick-style": ["error", "promise" | "callback"]
+ "vue/next-tick-style": ["error", "promise" | "await" | "callback"]
}
```
- `"promise"` (default) ... requires using the promise version.
+- `"await"` ... requires using the await syntax version.
- `"callback"` ... requires using the callback version. Use this if you use a Vue version below v2.1.0.
+### `"await"`
+
+
+
+```vue
+
+```
+
+
### `"callback"`
diff --git a/lib/rules/next-tick-style.js b/lib/rules/next-tick-style.js
index 08cc85a1b..289d55c53 100644
--- a/lib/rules/next-tick-style.js
+++ b/lib/rules/next-tick-style.js
@@ -79,17 +79,44 @@ function isAwaitedPromise(callExpression) {
)
}
+/**
+ * @param {CallExpression} callExpression
+ * @returns {boolean}
+ */
+
+/**
+ * @param {Expression | SpreadElement} callback
+ * @param {SourceCode} sourceCode
+ * @returns {string}
+ */
+function extractCallbackBody(callback, sourceCode) {
+ if (
+ callback.type !== 'FunctionExpression' &&
+ callback.type !== 'ArrowFunctionExpression'
+ ) {
+ return ''
+ }
+
+ if (callback.body.type === 'BlockStatement') {
+ return sourceCode.getText(callback.body).trim()
+ }
+
+ return sourceCode.getText(callback.body)
+}
+
module.exports = {
meta: {
type: 'suggestion',
docs: {
- description: 'enforce Promise or callback style in `nextTick`',
+ description: 'enforce Promise, Await or callback style in `nextTick`',
categories: undefined,
url: 'https://eslint.vuejs.org/rules/next-tick-style.html'
},
fixable: 'code',
- schema: [{ enum: ['promise', 'callback'] }],
+ schema: [{ enum: ['promise', 'await', 'callback'] }],
messages: {
+ useAwait:
+ 'Use the await keyword with the Promise returned by `nextTick` instead of passing a callback function or using `.then()`.',
usePromise:
'Use the Promise returned by `nextTick` instead of passing a callback function.',
useCallback:
@@ -123,6 +150,66 @@ module.exports = {
return
}
+ if (preferredStyle === 'await') {
+ if (
+ callExpression.arguments.length > 0 ||
+ callExpression.parent.type !== 'AwaitExpression'
+ ) {
+ context.report({
+ node,
+ messageId: 'useAwait',
+ fix(fixer) {
+ const sourceCode = context.getSourceCode()
+
+ // Handle callback to await conversion
+ if (callExpression.arguments.length === 1) {
+ if (callExpression.parent.type !== 'ExpressionStatement') {
+ return null
+ }
+
+ const [args] = callExpression.arguments
+ let callbackBody = null
+
+ callbackBody =
+ args.type === 'ArrowFunctionExpression' ||
+ (args.type === 'FunctionExpression' && !args.generator)
+ ? extractCallbackBody(args, sourceCode)
+ : `${sourceCode.getText(args)}()`
+
+ const nextTickCaller = sourceCode.getText(
+ callExpression.callee
+ )
+ return fixer.replaceText(
+ callExpression.parent,
+ `await ${nextTickCaller}();${callbackBody};`
+ )
+ }
+
+ // Handle promise to await conversion
+ if (isAwaitedPromise(callExpression)) {
+ const thenCall = callExpression.parent.parent
+ if (thenCall === null || thenCall.type !== 'CallExpression') {
+ return null
+ }
+ const [thenCallback] = thenCall.arguments
+ if (thenCallback) {
+ const thenCallbackBody = extractCallbackBody(
+ thenCallback,
+ sourceCode
+ )
+ return fixer.replaceText(
+ thenCall,
+ `await ${sourceCode.getText(callExpression)};${thenCallbackBody}`
+ )
+ }
+ }
+ return null
+ }
+ })
+ }
+
+ return
+ }
if (
callExpression.arguments.length > 0 ||
!isAwaitedPromise(callExpression)
diff --git a/tests/lib/rules/next-tick-style.js b/tests/lib/rules/next-tick-style.js
index c143c8a40..899be6730 100644
--- a/tests/lib/rules/next-tick-style.js
+++ b/tests/lib/rules/next-tick-style.js
@@ -54,6 +54,18 @@ tester.run('next-tick-style', rule, {
}`,
options: ['promise']
},
+ {
+ filename: 'test.vue',
+ code: ``,
+ options: ['await']
+ },
{
filename: 'test.vue',
code: ``,
+ options: ['await']
+ },
+ {
+ filename: 'test.vue',
+ code: ``,
options: ['callback']
}
],
@@ -237,6 +265,98 @@ tester.run('next-tick-style', rule, {
}
]
},
+ {
+ filename: 'test.vue',
+ code: ``,
+ output: ``,
+ options: ['await'],
+ errors: [
+ {
+ message:
+ 'Use the await keyword with the Promise returned by `nextTick` instead of passing a callback function or using `.then()`.',
+ line: 4,
+ column: 16
+ },
+ {
+ message:
+ 'Use the await keyword with the Promise returned by `nextTick` instead of passing a callback function or using `.then()`.',
+ line: 5,
+ column: 15
+ },
+ {
+ message:
+ 'Use the await keyword with the Promise returned by `nextTick` instead of passing a callback function or using `.then()`.',
+ line: 6,
+ column: 11
+ },
+ {
+ message:
+ 'Use the await keyword with the Promise returned by `nextTick` instead of passing a callback function or using `.then()`.',
+ line: 8,
+ column: 16
+ },
+ {
+ message:
+ 'Use the await keyword with the Promise returned by `nextTick` instead of passing a callback function or using `.then()`.',
+ line: 9,
+ column: 15
+ },
+ {
+ message:
+ 'Use the await keyword with the Promise returned by `nextTick` instead of passing a callback function or using `.then()`.',
+ line: 10,
+ column: 11
+ },
+ {
+ message:
+ 'Use the await keyword with the Promise returned by `nextTick` instead of passing a callback function or using `.then()`.',
+ line: 12,
+ column: 16
+ },
+ {
+ message:
+ 'Use the await keyword with the Promise returned by `nextTick` instead of passing a callback function or using `.then()`.',
+ line: 13,
+ column: 15
+ },
+ {
+ message:
+ 'Use the await keyword with the Promise returned by `nextTick` instead of passing a callback function or using `.then()`.',
+ line: 14,
+ column: 11
+ }
+ ]
+ },
{
filename: 'test.vue',
code: `