Skip to content

Commit 41992cd

Browse files
authored
fix: false positive with Set/Map-initialized private class properties in no-array-prototype-extensions rule (#1544)
1 parent ae70c0a commit 41992cd

File tree

2 files changed

+89
-5
lines changed

2 files changed

+89
-5
lines changed

lib/rules/no-array-prototype-extensions.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,15 @@ module.exports = {
171171
node.callee.type === 'MemberExpression' &&
172172
node.callee.object.type === 'MemberExpression' &&
173173
node.callee.object.object.type === 'ThisExpression' &&
174-
node.callee.object.property.type === 'Identifier' &&
174+
['Identifier', 'PrivateIdentifier', 'PrivateName'].includes(
175+
node.callee.object.property.type
176+
) &&
175177
classStack.peek() &&
176-
classStack.peek().classPropertiesToIgnore.has(node.callee.object.property.name)
178+
classStack.peek().classPropertiesToIgnore.has(
179+
node.callee.object.property.type === 'Identifier'
180+
? node.callee.object.property.name
181+
: `#${node.callee.object.property.name}` // Add # for private properties to avoid confusing public/private properties.
182+
)
177183
) {
178184
// Ignore when we can tell the class property was initialized to an instance of a non-array class.
179185
// Example:
@@ -241,14 +247,15 @@ module.exports = {
241247
node.body.body
242248
.filter(
243249
(n) =>
244-
isClassPropertyOrPropertyDefinition(n) &&
245-
n.key.type === 'Identifier' &&
250+
// ClassProperty / ClassPrivateProperty / PrivateName are for ESLint v7.
251+
(isClassPropertyOrPropertyDefinition(n) || n.type === 'ClassPrivateProperty') &&
252+
['Identifier', 'PrivateIdentifier', 'PrivateName'].includes(n.key.type) &&
246253
n.value &&
247254
n.value.type === 'NewExpression' &&
248255
n.value.callee.type === 'Identifier' &&
249256
KNOWN_NON_ARRAY_CLASSES.has(n.value.callee.name)
250257
)
251-
.map((n) => n.key.name)
258+
.map((n) => (n.key.type === 'Identifier' ? n.key.name : `#${n.key.name}`)) // Add # for private properties to avoid confusing public/private properties.
252259
);
253260

254261
classStack.push({ node, classPropertiesToIgnore });

tests/lib/rules/no-array-prototype-extensions.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ ruleTester.run('no-array-prototype-extensions', rule, {
9797
}
9898
}`,
9999

100+
// Class property definition (private) with non-array class.
101+
`class MyClass {
102+
#foo = new Set();
103+
myFunc() {
104+
this.#foo.clear();
105+
}
106+
}`,
107+
100108
{
101109
// Class property definition with non-array class (TypeScript).
102110
code: `
@@ -110,6 +118,33 @@ ruleTester.run('no-array-prototype-extensions', rule, {
110118
parser: require.resolve('@typescript-eslint/parser'),
111119
},
112120

121+
{
122+
// Class property definition (private) with non-array class (TypeScript).
123+
code: `
124+
class MyClass {
125+
#foo: Set<UploadFile> = new TrackedSet();
126+
myFunc() {
127+
this.#foo.clear();
128+
}
129+
}
130+
`,
131+
parser: require.resolve('@typescript-eslint/parser'),
132+
},
133+
{
134+
// Class property definition (private) with non-array class (TypeScript) (does not confuse public/private properties).
135+
code: `
136+
class MyClass {
137+
#foo: Set<UploadFile> = new TrackedSet();
138+
foo: Array<UploadFile> = new Array();
139+
140+
myFunc() {
141+
this.#foo.clear();
142+
}
143+
}
144+
`,
145+
parser: require.resolve('@typescript-eslint/parser'),
146+
},
147+
113148
// TODO: handle non-Identifier property names:
114149
'foo["clear"]();',
115150
],
@@ -373,6 +408,18 @@ ruleTester.run('no-array-prototype-extensions', rule, {
373408
output: null,
374409
errors: [{ messageId: 'main', type: 'CallExpression' }],
375410
},
411+
{
412+
// Class property (private) with array value.
413+
code: `
414+
class MyClass {
415+
#foo = new Array();
416+
myFunc() {
417+
this.#foo.clear();
418+
}
419+
}`,
420+
output: null,
421+
errors: [{ messageId: 'main', type: 'CallExpression' }],
422+
},
376423
{
377424
// Class property with array value (TypeScript).
378425
code: `
@@ -387,6 +434,36 @@ ruleTester.run('no-array-prototype-extensions', rule, {
387434
parser: require.resolve('@typescript-eslint/parser'),
388435
errors: [{ messageId: 'main', type: 'CallExpression' }],
389436
},
437+
{
438+
// Class property (private) with array value (TypeScript).
439+
code: `
440+
class MyClass {
441+
#foo: Array<UploadFile> = new Array();
442+
myFunc() {
443+
this.#foo.clear();
444+
}
445+
}
446+
`,
447+
output: null,
448+
parser: require.resolve('@typescript-eslint/parser'),
449+
errors: [{ messageId: 'main', type: 'CallExpression' }],
450+
},
451+
{
452+
// Class property definition (private) with array class (TypeScript) (does not confuse public/private properties).
453+
code: `
454+
class MyClass {
455+
#foo: Array<UploadFile> = new Array();
456+
foo: Set<UploadFile> = new Set();
457+
458+
myFunc() {
459+
this.#foo.clear();
460+
}
461+
}
462+
`,
463+
output: null,
464+
parser: require.resolve('@typescript-eslint/parser'),
465+
errors: [{ messageId: 'main', type: 'CallExpression' }],
466+
},
390467
{
391468
// Class property with no value.
392469
code: `

0 commit comments

Comments
 (0)