Skip to content
This repository has been archived by the owner on Mar 19, 2024. It is now read-only.

Commit

Permalink
feat: add rule no-this-in-async-data
Browse files Browse the repository at this point in the history
  • Loading branch information
clarkdo committed Dec 5, 2018
1 parent e09a871 commit 96ce607
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 9 deletions.
107 changes: 107 additions & 0 deletions lib/rules/__test__/no-this-in-async-data.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* @fileoverview Prevent using this in asyncData
* @author Clark Du
*/
'use strict'

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

var rule = require('../no-this-in-async-data')

var RuleTester = require('eslint').RuleTester

const parserOptions = {
ecmaVersion: 2018,
sourceType: 'module'
}

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------

var ruleTester = new RuleTester()
ruleTester.run('no-this-in-async-data', rule, {

valid: [
{
filename: 'test.vue',
code: `
export default {
...foo,
asyncData() {
}
}
`,
parserOptions
}
],

invalid: [
{
filename: 'test.vue',
code: `
export default {
...foo,
asyncData() {
if(this.$route.path === 'foo') {}
}
}
`,
errors: [{
message: 'Unexpected this in asyncData.',
type: 'Identifier'
}],
parserOptions
},
{
filename: 'test.vue',
code: `
export default {
...foo,
async asyncData() {
if(this.$route.path === 'foo') {}
}
}
`,
errors: [{
message: 'Unexpected this in asyncData.',
type: 'Identifier'
}],
parserOptions
},
{
filename: 'test.vue',
code: `
export default {
...foo,
asyncData: () => {
if(this.$route.path === 'foo') {}
}
}
`,
errors: [{
message: 'Unexpected this in asyncData.',
type: 'Identifier'
}],
parserOptions
},
{
filename: 'test.vue',
code: `
export default {
...foo,
asyncData: function test() {
if(this.$route.path === 'foo') {}
}
}
`,
errors: [{
message: 'Unexpected this in asyncData.',
type: 'Identifier'
}],
parserOptions
}
]
})
51 changes: 45 additions & 6 deletions lib/rules/no-this-in-async-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@
*/
'use strict'

const utils = require('../utils')

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------

module.exports = {
meta: {
docs: {
description: 'Prevent using this in asyncData',
category: 'Fill me in',
recommended: false
description: 'disallow `this` in asyncData',
category: 'base'
},
fixable: null, // or "code" or "whitespace"
schema: [
Expand All @@ -26,20 +27,58 @@ module.exports = {

create: function (context) {
// variables should be defined here
const forbiddenNodes = []
let isThisUsed

// ----------------------------------------------------------------------
// Helpers
// ----------------------------------------------------------------------

function enterFunction () {
isThisUsed = false
}

function exitFunction (node) {
if (isThisUsed) {
forbiddenNodes.push(node)
}
}

function markThisUsed () {
isThisUsed = true
}

function getFuncNodeWithName (node, name) {
return node.properties.find(item => item.type === 'Property' &&
utils.getStaticPropertyName(item) === name &&
(item.value.type === 'ArrowFunctionExpression' || item.value.type === 'FunctionExpression')
)
}

// ----------------------------------------------------------------------
// Public
// ----------------------------------------------------------------------

return {
'FunctionExpression:exit' (node) {
FunctionExpression: enterFunction,
'FunctionExpression:exit': exitFunction,
ArrowFunctionExpression: enterFunction,
'ArrowFunctionExpression:exit': exitFunction,
ThisExpression: markThisUsed,
Super: markThisUsed,
...utils.executeOnVue(context, obj => {
const node = getFuncNodeWithName(obj, 'asyncData')
if (!node) return

// give me methods
}
forbiddenNodes.forEach(el => {
if (node.value === el) {
context.report({
node: node.key,
messageId: 'noThis'
})
}
})
})
}
}
}
5 changes: 2 additions & 3 deletions lib/rules/no-this-in-fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
module.exports = {
meta: {
docs: {
description: 'Prevent using this in fetch',
category: 'Fill me in',
recommended: false
description: 'disallow `this` in fetch',
category: 'base'
},
fixable: null, // or "code" or "whitespace"
schema: [
Expand Down
1 change: 1 addition & 0 deletions lib/utils/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('eslint-plugin-vue/lib/utils')

0 comments on commit 96ce607

Please sign in to comment.