@@ -7,21 +7,21 @@ import { type RuleContext } from "@typescript-eslint/utils/ts-eslint";
7
7
import { deepmerge } from "deepmerge-ts" ;
8
8
9
9
import {
10
- type IgnoreAccessorPatternOption ,
11
- type IgnoreIdentifierPatternOption ,
12
- type IgnoreClassesOption ,
13
- shouldIgnorePattern ,
14
- shouldIgnoreClasses ,
15
10
ignoreAccessorPatternOptionSchema ,
16
11
ignoreClassesOptionSchema ,
17
12
ignoreIdentifierPatternOptionSchema ,
13
+ shouldIgnoreClasses ,
14
+ shouldIgnorePattern ,
15
+ type IgnoreAccessorPatternOption ,
16
+ type IgnoreClassesOption ,
17
+ type IgnoreIdentifierPatternOption ,
18
18
} from "#eslint-plugin-functional/options" ;
19
19
import { isExpected } from "#eslint-plugin-functional/utils/misc" ;
20
20
import {
21
21
createRule ,
22
22
getTypeOfNode ,
23
- type RuleResult ,
24
23
type NamedCreateRuleMetaWithCategory ,
24
+ type RuleResult ,
25
25
} from "#eslint-plugin-functional/utils/rule" ;
26
26
import {
27
27
findRootIdentifier ,
@@ -163,6 +163,22 @@ const objectConstructorMutatorFunctions = new Set([
163
163
"setPrototypeOf" ,
164
164
] ) ;
165
165
166
+ /**
167
+ * Object constructor functions that return a new array.
168
+ */
169
+ const objectConstructorNewObjectReturningMethods = [
170
+ "create" ,
171
+ "entries" ,
172
+ "fromEntries" ,
173
+ "getOwnPropertyDescriptor" ,
174
+ "getOwnPropertyDescriptors" ,
175
+ "getOwnPropertyNames" ,
176
+ "getOwnPropertySymbols" ,
177
+ "groupBy" ,
178
+ "keys" ,
179
+ "values" ,
180
+ ] ;
181
+
166
182
/**
167
183
* Check if the given assignment expression violates this rule.
168
184
*/
@@ -330,27 +346,55 @@ function isInChainCallAndFollowsNew(
330
346
node : TSESTree . MemberExpression ,
331
347
context : Readonly < RuleContext < keyof typeof errorMessages , Options > > ,
332
348
) : boolean {
333
- return (
334
- // Check for: [0, 1, 2]
335
- isArrayExpression ( node . object ) ||
336
- // Check for: new Array()
337
- ( isNewExpression ( node . object ) &&
338
- isArrayConstructorType ( getTypeOfNode ( node . object . callee , context ) ) ) ||
339
- ( isCallExpression ( node . object ) &&
340
- isMemberExpression ( node . object . callee ) &&
341
- isIdentifier ( node . object . callee . property ) &&
342
- // Check for: Array.from(iterable)
343
- ( ( arrayConstructorFunctions . some (
349
+ // Check for: [0, 1, 2]
350
+ if ( isArrayExpression ( node . object ) ) {
351
+ return true ;
352
+ }
353
+
354
+ // Check for: new Array()
355
+ if (
356
+ isNewExpression ( node . object ) &&
357
+ isArrayConstructorType ( getTypeOfNode ( node . object . callee , context ) )
358
+ ) {
359
+ return true ;
360
+ }
361
+
362
+ if (
363
+ isCallExpression ( node . object ) &&
364
+ isMemberExpression ( node . object . callee ) &&
365
+ isIdentifier ( node . object . callee . property )
366
+ ) {
367
+ // Check for: Array.from(iterable)
368
+ if (
369
+ arrayConstructorFunctions . some (
370
+ isExpected ( node . object . callee . property . name ) ,
371
+ ) &&
372
+ isArrayConstructorType ( getTypeOfNode ( node . object . callee . object , context ) )
373
+ ) {
374
+ return true ;
375
+ }
376
+
377
+ // Check for: array.slice(0)
378
+ if (
379
+ arrayNewObjectReturningMethods . some (
380
+ isExpected ( node . object . callee . property . name ) ,
381
+ )
382
+ ) {
383
+ return true ;
384
+ }
385
+
386
+ // Check for: Object.entries(object)
387
+ if (
388
+ objectConstructorNewObjectReturningMethods . some (
344
389
isExpected ( node . object . callee . property . name ) ,
345
390
) &&
346
- isArrayConstructorType (
347
- getTypeOfNode ( node . object . callee . object , context ) ,
348
- ) ) ||
349
- // Check for: array.slice(0)
350
- arrayNewObjectReturningMethods . some (
351
- isExpected ( node . object . callee . property . name ) ,
352
- ) ) )
353
- ) ;
391
+ isObjectConstructorType ( getTypeOfNode ( node . object . callee . object , context ) )
392
+ ) {
393
+ return true ;
394
+ }
395
+ }
396
+
397
+ return false ;
354
398
}
355
399
356
400
/**
0 commit comments