Skip to content

Commit 47960f6

Browse files
authored
Fixed false positives for getter/setter in vue/no-dupe-keys rule (#1190)
1 parent 1700708 commit 47960f6

File tree

2 files changed

+231
-56
lines changed

2 files changed

+231
-56
lines changed

lib/utils/index.js

+60-22
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
* @typedef {import('vue-eslint-parser').AST.ESLintFunctionExpression} FunctionExpression
1919
* @typedef {import('vue-eslint-parser').AST.ESLintBlockStatement} BlockStatement
2020
* @typedef {import('vue-eslint-parser').AST.ESLintNode} ESLintNode
21+
*
22+
* @typedef {import('vue-eslint-parser').AST.ESLintArrowFunctionExpression | { type: 'ArrowFunctionExpression', body: BlockStatement | Expression } } ArrowFunctionExpression
2123
*/
2224

2325
/**
@@ -37,6 +39,11 @@
3739
/**
3840
* @typedef { {key: string, value: BlockStatement} } ComponentComputedProperty
3941
*/
42+
/**
43+
* @typedef { { name: string, groupName: string, node: Literal | TemplateLiteral } } ComponentArrayPropertyData
44+
* @typedef { { name: string, groupName: string, node: Identifier | Literal | TemplateLiteral } } ComponentObjectPropertyData
45+
* @typedef { ComponentArrayPropertyData | ComponentObjectPropertyData } ComponentPropertyData
46+
*/
4047

4148
// ------------------------------------------------------------------------------
4249
// Helpers
@@ -799,14 +806,17 @@ module.exports = {
799806
},
800807
/**
801808
* Return generator with all properties
802-
* @param {ASTNode} node Node to check
803-
* @param {Set} groups Name of parent group
809+
* @param {ObjectExpression} node Node to check
810+
* @param {Set<string>} groups Name of parent group
811+
* @returns {IterableIterator<ComponentPropertyData>}
804812
*/
805813
* iterateProperties (node, groups) {
806-
const nodes = node.properties.filter(p => p.type === 'Property' && groups.has(getStaticPropertyName(p.key)))
807-
for (const item of nodes) {
808-
const name = getStaticPropertyName(item.key)
809-
if (!name) continue
814+
for (const item of node.properties) {
815+
if (item.type !== 'Property') {
816+
continue
817+
}
818+
const name = getStaticPropertyName(item)
819+
if (!name || !groups.has(name)) continue
810820

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

823833
/**
824834
* Return generator with all elements inside ArrayExpression
825-
* @param {ASTNode} node Node to check
835+
* @param {ArrayExpression} node Node to check
826836
* @param {string} groupName Name of parent group
837+
* @returns {IterableIterator<ComponentArrayPropertyData>}
827838
*/
828839
* iterateArrayExpression (node, groupName) {
829840
assert(node.type === 'ArrayExpression')
830841
for (const item of node.elements) {
831-
const name = getStaticPropertyName(item)
832-
if (name) {
833-
const obj = { name, groupName, node: item }
834-
yield obj
842+
if (item.type === 'Literal' || item.type === 'TemplateLiteral') {
843+
const name = getStaticPropertyName(item)
844+
if (name) {
845+
yield { name, groupName, node: item }
846+
}
835847
}
836848
}
837849
},
838850

839851
/**
840852
* Return generator with all elements inside ObjectExpression
841-
* @param {ASTNode} node Node to check
853+
* @param {ObjectExpression} node Node to check
842854
* @param {string} groupName Name of parent group
855+
* @returns {IterableIterator<ComponentObjectPropertyData>}
843856
*/
844857
* iterateObjectExpression (node, groupName) {
845858
assert(node.type === 'ObjectExpression')
859+
let usedGetter
846860
for (const item of node.properties) {
847-
const name = getStaticPropertyName(item)
848-
if (name) {
849-
const obj = { name, groupName, node: item.key }
850-
yield obj
861+
if (item.type === 'Property') {
862+
const key = item.key
863+
if (key.type === 'Identifier' || key.type === 'Literal' || key.type === 'TemplateLiteral') {
864+
const name = getStaticPropertyName(item)
865+
if (name) {
866+
if (item.kind === 'set') {
867+
// find getter pair
868+
if (!usedGetter) { usedGetter = new Set() }
869+
if (node.properties.some(item2 => {
870+
if (item2.type === 'Property' && item2.kind === 'get' && !usedGetter.has(item2)) {
871+
const getterName = getStaticPropertyName(item2)
872+
if (getterName === name) {
873+
usedGetter.add(item2)
874+
return true
875+
}
876+
}
877+
return false
878+
})) {
879+
// has getter pair
880+
continue
881+
}
882+
}
883+
yield { name, groupName, node: key }
884+
}
885+
}
851886
}
852887
}
853888
},
854889

855890
/**
856891
* Return generator with all elements inside FunctionExpression
857-
* @param {ASTNode} node Node to check
892+
* @param {FunctionExpression} node Node to check
858893
* @param {string} groupName Name of parent group
894+
* @returns {IterableIterator<ComponentObjectPropertyData>}
859895
*/
860896
* iterateFunctionExpression (node, groupName) {
861897
assert(node.type === 'FunctionExpression')
@@ -870,19 +906,21 @@ module.exports = {
870906

871907
/**
872908
* Return generator with all elements inside ArrowFunctionExpression
873-
* @param {ASTNode} node Node to check
909+
* @param {ArrowFunctionExpression} node Node to check
874910
* @param {string} groupName Name of parent group
911+
* @returns {IterableIterator<ComponentObjectPropertyData>}
875912
*/
876913
* iterateArrowFunctionExpression (node, groupName) {
877914
assert(node.type === 'ArrowFunctionExpression')
878-
if (node.body.type === 'BlockStatement') {
879-
for (const item of node.body.body) {
915+
const body = node.body
916+
if (body.type === 'BlockStatement') {
917+
for (const item of body.body) {
880918
if (item.type === 'ReturnStatement' && item.argument && item.argument.type === 'ObjectExpression') {
881919
yield * this.iterateObjectExpression(item.argument, groupName)
882920
}
883921
}
884-
} else if (node.body.type === 'ObjectExpression') {
885-
yield * this.iterateObjectExpression(node.body, groupName)
922+
} else if (body.type === 'ObjectExpression') {
923+
yield * this.iterateObjectExpression(body, groupName)
886924
}
887925
},
888926

0 commit comments

Comments
 (0)