Skip to content

Commit 636cead

Browse files
object88gajus
authored andcommitted
fix: no-dupe-keys with legal duplicated keys (#148)
1 parent 66d04e8 commit 636cead

File tree

2 files changed

+144
-4
lines changed

2 files changed

+144
-4
lines changed

src/rules/noDupeKeys.js

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,66 @@ export default (context) => {
1212
});
1313
};
1414

15+
const analizeElement = (element) => {
16+
const {type} = element;
17+
let value;
18+
19+
switch (type) {
20+
case 'GenericTypeAnnotation':
21+
value = element.id.name;
22+
break;
23+
case 'ObjectTypeAnnotation':
24+
// eslint-disable-next-line no-use-before-define
25+
value = builObjectStructure(element.properties);
26+
break;
27+
case 'TupleTypeAnnotation':
28+
// eslint-disable-next-line no-use-before-define
29+
value = buildArrayStructure(element.types);
30+
break;
31+
default:
32+
value = element.value;
33+
break;
34+
}
35+
36+
return {
37+
type,
38+
value
39+
};
40+
};
41+
42+
const buildArrayStructure = (elements) => {
43+
return _.map(elements, (element) => {
44+
return analizeElement(element);
45+
});
46+
};
47+
48+
const builObjectStructure = (properties) => {
49+
return _.map(properties, (property) => {
50+
const element = analizeElement(property.value);
51+
52+
return Object.assign(element, {
53+
name: getParameterName(property, context)
54+
});
55+
});
56+
};
57+
1558
const checkForDuplicates = (node) => {
1659
const haystack = [];
1760

1861
_.forEach(node.properties, (identifierNode) => {
19-
const needle = getParameterName(identifierNode, context);
62+
const needle = {name: getParameterName(identifierNode, context)};
63+
64+
if (identifierNode.value.type === 'FunctionTypeAnnotation') {
65+
needle.args = _.map(identifierNode.value.params, (param) => {
66+
return analizeElement(param.typeAnnotation);
67+
});
68+
}
69+
70+
const match = _.some(haystack, (existingNeedle) => {
71+
return _.isEqual(existingNeedle, needle);
72+
});
2073

21-
if (_.includes(haystack, needle)) {
74+
if (match) {
2275
report(identifierNode);
2376
} else {
2477
haystack.push(needle);

tests/rules/assertions/noDupeKeys.js

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,59 @@
11
export default {
22
invalid: [
33
{
4-
code: 'type FooType = { a: number, b: string, a: number }',
4+
code: 'type f = { a: number, b: string, a: number }',
5+
errors: [{message: 'Duplicate property.'}]
6+
},
7+
{
8+
code: 'type f = { a: number, b: string, a: string }',
9+
errors: [{message: 'Duplicate property.'}]
10+
},
11+
{
12+
code: 'type f = { get(key: "a"): string, get(key: "a"): string }',
13+
errors: [{message: 'Duplicate property.'}]
14+
},
15+
{
16+
code: 'type f = { get(key: 1): string, get(key: 1): string }',
17+
errors: [{message: 'Duplicate property.'}]
18+
},
19+
{
20+
code: 'type f = { get(key: 1.1): string, get(key: 1.1): string }',
21+
errors: [{message: 'Duplicate property.'}]
22+
},
23+
{
24+
code: 'type f = { get(key: true): string, get(key: true): string }',
525
errors: [{message: 'Duplicate property.'}]
626
},
727
{
8-
code: 'type FooType = { a: number, b: string, a: string }',
28+
code: 'type f = { get(key: {a: 1}): string, get(key: {a: 1}):string }',
29+
errors: [{message: 'Duplicate property.'}]
30+
},
31+
{
32+
code: 'var a = "a"; type f = { get(key: a): string, get(key: a): string }',
33+
errors: [{message: 'Duplicate property.'}]
34+
},
35+
{
36+
code: 'var b = 1; type f = { get(key: b): string, get(key: b): string }',
37+
errors: [{message: 'Duplicate property.'}]
38+
},
39+
{
40+
code: 'var c = true; type f = { get(key: c): string, get(key: c): string }',
41+
errors: [{message: 'Duplicate property.'}]
42+
},
43+
{
44+
code: 'var d = {}; type f = { get(key: d): string, get(key: d): string }',
45+
errors: [{message: 'Duplicate property.'}]
46+
},
47+
{
48+
code: 'var e = []; type f = { get(key: e): string, get(key: e): string }',
49+
errors: [{message: 'Duplicate property.'}]
50+
},
51+
{
52+
code: 'var e = [1, "a"]; type f = { get(key: e): string, get(key: e): string }',
53+
errors: [{message: 'Duplicate property.'}]
54+
},
55+
{
56+
code: 'function fn() {}; type f = { get(key: fn): string, get(key: fn): string }',
957
errors: [{message: 'Duplicate property.'}]
1058
}
1159
],
@@ -20,6 +68,45 @@ export default {
2068
onlyFilesWithFlowAnnotation: true
2169
}
2270
}
71+
},
72+
{
73+
code: 'type f = { get(key: "a"): string, get(key: "b"): string }'
74+
},
75+
{
76+
code: 'type f = { get(key: 1): string, get(key: 2): string }'
77+
},
78+
{
79+
code: 'type f = { get(key: 1.1): string, get(key: 1.2): string }'
80+
},
81+
{
82+
code: 'type f = { get(key: true): string, get(key: false): string }'
83+
},
84+
{
85+
code: 'type f = { get(key: ["a", 1]): string, get(key: ["a", 2]): string }'
86+
},
87+
{
88+
code: 'type f = { get(key: ["a", ["b", 1]]): string, get(key: ["a", ["b", 2]]): string }'
89+
},
90+
{
91+
code: 'type f = { a: number, b: string, c: number }'
92+
},
93+
{
94+
code: 'type f = { get(key: "a"): string, get(key: "b"): string }'
95+
},
96+
{
97+
code: 'type f = { get(key: "a"): string, get(key: "a", key2: "b"): string }'
98+
},
99+
{
100+
code: 'type f = { get(key: "a"): string, get(key: 1): string }'
101+
},
102+
{
103+
code: 'type f = { get(key: { a: 1 }): string, get(key: { a: 2 }): string}'
104+
},
105+
{
106+
code: 'var a = {}; var b = {}; type f = { get(key: a): string, get(key: b): string }'
107+
},
108+
{
109+
code: 'var a = 1; var b = 1; type f = { get(key: a): string, get(key: b): string }'
23110
}
24111
]
25112
};

0 commit comments

Comments
 (0)