Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed false positives for getter/setter in vue/no-dupe-keys rule #1190

Merged
merged 1 commit into from Jun 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
82 changes: 60 additions & 22 deletions lib/utils/index.js
Expand Up @@ -18,6 +18,8 @@
* @typedef {import('vue-eslint-parser').AST.ESLintFunctionExpression} FunctionExpression
* @typedef {import('vue-eslint-parser').AST.ESLintBlockStatement} BlockStatement
* @typedef {import('vue-eslint-parser').AST.ESLintNode} ESLintNode
*
* @typedef {import('vue-eslint-parser').AST.ESLintArrowFunctionExpression | { type: 'ArrowFunctionExpression', body: BlockStatement | Expression } } ArrowFunctionExpression
*/

/**
Expand All @@ -37,6 +39,11 @@
/**
* @typedef { {key: string, value: BlockStatement} } ComponentComputedProperty
*/
/**
* @typedef { { name: string, groupName: string, node: Literal | TemplateLiteral } } ComponentArrayPropertyData
* @typedef { { name: string, groupName: string, node: Identifier | Literal | TemplateLiteral } } ComponentObjectPropertyData
* @typedef { ComponentArrayPropertyData | ComponentObjectPropertyData } ComponentPropertyData
*/

// ------------------------------------------------------------------------------
// Helpers
Expand Down Expand Up @@ -799,14 +806,17 @@ module.exports = {
},
/**
* Return generator with all properties
* @param {ASTNode} node Node to check
* @param {Set} groups Name of parent group
* @param {ObjectExpression} node Node to check
* @param {Set<string>} groups Name of parent group
* @returns {IterableIterator<ComponentPropertyData>}
*/
* iterateProperties (node, groups) {
const nodes = node.properties.filter(p => p.type === 'Property' && groups.has(getStaticPropertyName(p.key)))
for (const item of nodes) {
const name = getStaticPropertyName(item.key)
if (!name) continue
for (const item of node.properties) {
if (item.type !== 'Property') {
continue
}
const name = getStaticPropertyName(item)
if (!name || !groups.has(name)) continue

if (item.value.type === 'ArrayExpression') {
yield * this.iterateArrayExpression(item.value, name)
Expand All @@ -822,40 +832,66 @@ module.exports = {

/**
* Return generator with all elements inside ArrayExpression
* @param {ASTNode} node Node to check
* @param {ArrayExpression} node Node to check
* @param {string} groupName Name of parent group
* @returns {IterableIterator<ComponentArrayPropertyData>}
*/
* iterateArrayExpression (node, groupName) {
assert(node.type === 'ArrayExpression')
for (const item of node.elements) {
const name = getStaticPropertyName(item)
if (name) {
const obj = { name, groupName, node: item }
yield obj
if (item.type === 'Literal' || item.type === 'TemplateLiteral') {
const name = getStaticPropertyName(item)
if (name) {
yield { name, groupName, node: item }
}
}
}
},

/**
* Return generator with all elements inside ObjectExpression
* @param {ASTNode} node Node to check
* @param {ObjectExpression} node Node to check
* @param {string} groupName Name of parent group
* @returns {IterableIterator<ComponentObjectPropertyData>}
*/
* iterateObjectExpression (node, groupName) {
assert(node.type === 'ObjectExpression')
let usedGetter
for (const item of node.properties) {
const name = getStaticPropertyName(item)
if (name) {
const obj = { name, groupName, node: item.key }
yield obj
if (item.type === 'Property') {
const key = item.key
if (key.type === 'Identifier' || key.type === 'Literal' || key.type === 'TemplateLiteral') {
const name = getStaticPropertyName(item)
if (name) {
if (item.kind === 'set') {
// find getter pair
if (!usedGetter) { usedGetter = new Set() }
if (node.properties.some(item2 => {
if (item2.type === 'Property' && item2.kind === 'get' && !usedGetter.has(item2)) {
const getterName = getStaticPropertyName(item2)
if (getterName === name) {
usedGetter.add(item2)
return true
}
}
return false
})) {
// has getter pair
continue
}
}
yield { name, groupName, node: key }
}
}
}
}
},

/**
* Return generator with all elements inside FunctionExpression
* @param {ASTNode} node Node to check
* @param {FunctionExpression} node Node to check
* @param {string} groupName Name of parent group
* @returns {IterableIterator<ComponentObjectPropertyData>}
*/
* iterateFunctionExpression (node, groupName) {
assert(node.type === 'FunctionExpression')
Expand All @@ -870,19 +906,21 @@ module.exports = {

/**
* Return generator with all elements inside ArrowFunctionExpression
* @param {ASTNode} node Node to check
* @param {ArrowFunctionExpression} node Node to check
* @param {string} groupName Name of parent group
* @returns {IterableIterator<ComponentObjectPropertyData>}
*/
* iterateArrowFunctionExpression (node, groupName) {
assert(node.type === 'ArrowFunctionExpression')
if (node.body.type === 'BlockStatement') {
for (const item of node.body.body) {
const body = node.body
if (body.type === 'BlockStatement') {
for (const item of body.body) {
if (item.type === 'ReturnStatement' && item.argument && item.argument.type === 'ObjectExpression') {
yield * this.iterateObjectExpression(item.argument, groupName)
}
}
} else if (node.body.type === 'ObjectExpression') {
yield * this.iterateObjectExpression(node.body, groupName)
} else if (body.type === 'ObjectExpression') {
yield * this.iterateObjectExpression(body, groupName)
}
},

Expand Down