Skip to content

Commit

Permalink
Changed vue/no-deprecated-dollar-listeners-api and `vue/no-deprecat…
Browse files Browse the repository at this point in the history
…ed-events-api` rules to track the `this` variable. (#1143)
  • Loading branch information
ota-meshi committed May 19, 2020
1 parent c54b13a commit d191481
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 9 deletions.
14 changes: 11 additions & 3 deletions lib/rules/no-deprecated-dollar-listeners-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,19 @@ module.exports = {
},
utils.defineVueVisitor(context,
{
'MemberExpression > ThisExpression' (node) {
if (node.parent.property.name !== '$listeners') return
'MemberExpression' (node) {
if (
node.property.type !== 'Identifier' ||
node.property.name !== '$listeners'
) {
return
}
if (!utils.isThis(node.object, context)) {
return
}

context.report({
node: node.parent.property,
node: node.property,
messageId: 'deprecated'
})
}
Expand Down
16 changes: 13 additions & 3 deletions lib/rules/no-deprecated-events-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,21 @@ module.exports = {
create (context) {
return utils.defineVueVisitor(context,
{
'CallExpression > MemberExpression > ThisExpression' (node) {
if (!['$on', '$off', '$once'].includes(node.parent.property.name)) return
'CallExpression > MemberExpression' (node) {
const call = node.parent
if (
call.callee !== node ||
node.property.type !== 'Identifier' ||
!['$on', '$off', '$once'].includes(node.property.name)
) {
return
}
if (!utils.isThis(node.object, context)) {
return
}

context.report({
node: node.parent.parent,
node: node.property,
messageId: 'noDeprecatedEventsApi'
})
}
Expand Down
3 changes: 1 addition & 2 deletions lib/rules/require-explicit-emits.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,7 @@ module.exports = {

// verify $emit
if (emit && emit.name === '$emit') {
const objectType = emit.member.object.type
if (objectType === 'Identifier' || objectType === 'ThisExpression') {
if (utils.isThis(emit.member.object, context)) {
// verify this.$emit()
verify(emitsDeclarations, nameLiteralNode, vueNode)
}
Expand Down
30 changes: 29 additions & 1 deletion lib/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const VOID_ELEMENT_NAMES = new Set(require('./void-elements.json'))
const assert = require('assert')
const path = require('path')
const vueEslintParser = require('vue-eslint-parser')
const { findVariable } = require('eslint-utils')

/**
* @type { WeakMap<RuleContext, Token[]> }
Expand Down Expand Up @@ -855,7 +856,34 @@ module.exports = {
* @param {T} node
* @return {T}
*/
unwrapTypes
unwrapTypes,

/**
* Check whether the given node is `this` or variable that stores `this`.
* @param {ASTNode} node The node to check
* @returns {boolean} `true` if the given node is `this`.
*/
isThis (node, context) {
if (node.type === 'ThisExpression') {
return true
}
if (node.type !== 'Identifier') {
return false
}
const variable = findVariable(context.getScope(), node)

if (variable != null && variable.defs.length === 1) {
const def = variable.defs[0]
if (
def.parent &&
def.parent.kind === 'const' &&
def.node.id.type === 'Identifier'
) {
return def.node && def.node.init && def.node.init.type === 'ThisExpression'
}
}
return false
}
}

/**
Expand Down
62 changes: 62 additions & 0 deletions tests/lib/rules/no-deprecated-dollar-listeners-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,21 @@ ruleTester.run('no-deprecated-dollar-listeners-api', rule, {
}
</script>
`
},
{
filename: 'test.vue',
code: `
<script>
export default {
computed: {
foo () {
const {vm} = this
return vm.$listeners
}
}
}
</script>
`
}
],

Expand Down Expand Up @@ -179,6 +194,53 @@ ruleTester.run('no-deprecated-dollar-listeners-api', rule, {
endColumn: 33
}
]
},
{
filename: 'test.vue',
code: `
<script>
export default {
computed: {
foo () {
const vm = this
return vm.$listeners
}
}
}
</script>
`,
errors: [
{
line: 7,
column: 25,
messageId: 'deprecated'
}
]
},
{
filename: 'test.vue',
code: `
<script>
export default {
computed: {
foo () {
const vm = this
function fn() {
return vm.$listeners
}
return fn()
}
}
}
</script>
`,
errors: [
{
line: 8,
column: 27,
messageId: 'deprecated'
}
]
}
]
})
29 changes: 29 additions & 0 deletions tests/lib/rules/no-deprecated-events-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,17 @@ ruleTester.run('no-deprecated-events-api', rule, {
}
`,
parserOptions
},
{
filename: 'test.vue',
code: `
export default {
mounted () {
a(this.$on)
}
}
`,
parserOptions
}
],

Expand Down Expand Up @@ -155,6 +166,24 @@ ruleTester.run('no-deprecated-events-api', rule, {
message: 'The Events api `$on`, `$off` `$once` is deprecated. Using external library instead, for example mitt.',
line: 4
}]
},
{
filename: 'test.js',
code: `
app.component('some-comp', {
mounted () {
const vm = this
vm.$on('start', function (args) {
console.log('start', args)
})
}
})
`,
parserOptions,
errors: [{
message: 'The Events api `$on`, `$off` `$once` is deprecated. Using external library instead, for example mitt.',
line: 5
}]
}
]
})

0 comments on commit d191481

Please sign in to comment.