Skip to content

Commit

Permalink
Fix false positives for member call and autofix error in `vue/v-on-fu…
Browse files Browse the repository at this point in the history
…nction-call` rule. (#1146)
  • Loading branch information
ota-meshi committed May 21, 2020
1 parent 5750d7a commit f061f82
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 6 deletions.
32 changes: 26 additions & 6 deletions lib/rules/v-on-function-call.js
Expand Up @@ -9,6 +9,19 @@

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

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

/**
* Check whether the given token is a left parenthesis.
* @param {Token} token The token to check.
* @returns {boolean} `true` if the token is a left parenthesis.
*/
function isLeftParen (token) {
return token != null && token.type === 'Punctuator' && token.value === '('
}

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
Expand Down Expand Up @@ -40,17 +53,24 @@ module.exports = {
})
},

"VAttribute[directive=true][key.name.name='on'][key.argument!=null] VOnExpression > ExpressionStatement > *" (node) {
if (!always && node.type === 'CallExpression' && node.arguments.length === 0) {
"VAttribute[directive=true][key.name.name='on'][key.argument!=null] VOnExpression > ExpressionStatement > CallExpression" (node) {
if (!always && node.arguments.length === 0 && node.callee.type === 'Identifier') {
context.report({
node,
loc: node.loc,
message: "Method calls without arguments inside of 'v-on' directives must not have parentheses.",
fix: fixer => {
const nodeString = context.getSourceCode().getText().substring(node.range[0], node.range[1])
// This ensures that parens are also removed if they contain whitespace
const parensLength = nodeString.match(/\(\s*\)\s*$/)[0].length
return fixer.removeRange([node.end - parensLength, node.end])
const tokenStore = context.parserServices.getTemplateBodyTokenStore()
const rightToken = tokenStore.getLastToken(node)
const leftToken = tokenStore.getTokenAfter(node.callee, isLeftParen)
const tokens = tokenStore.getTokensBetween(leftToken, rightToken, { includeComments: true })

if (tokens.length) {
// The comment is included and cannot be fixed.
return null
}

return fixer.removeRange([leftToken.range[0], rightToken.range[1]])
}
})
}
Expand Down
34 changes: 34 additions & 0 deletions tests/lib/rules/v-on-function-call.js
Expand Up @@ -44,6 +44,33 @@ tester.run('v-on-function-call', rule, {
filename: 'test.vue',
code: '<template><div @click="foo"></div></template>',
options: ['never']
},
{
filename: 'test.vue',
code: '<template><div @click="foo.bar()"></div></template>'
},
{
filename: 'test.vue',
code: '<template><div @click="foo.bar()"></div></template>',
options: ['always']
},
{
filename: 'test.vue',
code: '<template><div @[foo()]="bar"></div></template>'
},
{
filename: 'test.vue',
code: '<template><div @[foo]="bar()"></div></template>',
options: ['always']
},
{
filename: 'test.vue',
code: '<template><div @click="()=>foo.bar()"></div></template>'
},
{
filename: 'test.vue',
code: '<template><div @click="()=>foo.bar()"></div></template>',
options: ['always']
}
],
invalid: [
Expand All @@ -67,6 +94,13 @@ tester.run('v-on-function-call', rule, {
output: `<template><div @click="foo"></div></template>`,
errors: ["Method calls without arguments inside of 'v-on' directives must not have parentheses."],
options: ['never']
},
{
filename: 'test.vue',
code: '<template><div @click="foo(/**/)"></div></template>',
output: null,
errors: ["Method calls without arguments inside of 'v-on' directives must not have parentheses."],
options: ['never']
}
]
})

0 comments on commit f061f82

Please sign in to comment.