@@ -25,6 +25,12 @@ export const minChainedCallDepth = createRule({
25
25
minimum : 1 ,
26
26
default : 100 ,
27
27
} ,
28
+ ignoreChainDeeperThan : {
29
+ type : 'integer' ,
30
+ minimum : 1 ,
31
+ maximum : 10 ,
32
+ default : 2 ,
33
+ } ,
28
34
} ,
29
35
additionalProperties : false ,
30
36
} ,
@@ -37,9 +43,13 @@ export const minChainedCallDepth = createRule({
37
43
{
38
44
maxLineLength : 100 ,
39
45
} ,
46
+ {
47
+ ignoreChainDeeperThan : 3 ,
48
+ } ,
40
49
] ,
41
50
create : context => {
42
51
const sourceCode = context . getSourceCode ( ) ;
52
+ let maxDepth = 0 ;
43
53
44
54
function getDepth ( node : TSESTree . MemberExpression | TSESTree . CallExpression ) : number {
45
55
let depth = 0 ;
@@ -88,29 +98,49 @@ export const minChainedCallDepth = createRule({
88
98
: node ;
89
99
90
100
if (
91
- // If the callee is not a member expression, we can skip.
101
+ // If the callee is not a member expression, skip.
92
102
// For example, root level calls like `foo();`.
93
103
callee . type !== AST_NODE_TYPES . MemberExpression
94
- // If the callee is a computed member expression, like `foo[bar]()`, we can skip.
104
+ // If the callee is a computed member expression, like `foo[bar]()`, skip.
95
105
|| callee . computed
96
106
/* eslint-disable-next-line @typescript-eslint/ban-ts-comment --
97
- * NewExpression is a possible callee object type
98
- */
107
+ * NewExpression is a possible callee object type
108
+ */
99
109
// @ts -ignore
100
110
|| callee . object . type === AST_NODE_TYPES . NewExpression
101
- // If the callee is already in the same line as it's object, we can skip.
111
+ // If the callee is already in the same line as it's object, skip.
102
112
|| callee . object . loc . end . line === callee . property . loc . start . line
103
113
) {
104
114
return ;
105
115
}
106
116
107
- // We only inline the first level of chained calls.
108
- // If the current call is nested inside another call, we can skip.
109
- if ( getDepth ( callee ) > 1 ) {
117
+ const currentDepth = getDepth ( callee ) ;
118
+
119
+ maxDepth = Math . max ( maxDepth , currentDepth ) ;
120
+
121
+ // Only affect the root level as the total depth is must be known.
122
+ // If the current call is nested inside another call, skip.
123
+ if ( currentDepth > 1 ) {
124
+ return ;
125
+ }
126
+
127
+ const { maxLineLength = 100 , ignoreChainDeeperThan = 2 } = context . options [ 0 ] ?? { } ;
128
+
129
+ // If the max depth is greater than ignore threshold, skip
130
+ //
131
+ // Example:
132
+ // ```ts
133
+ // Array(10)
134
+ // .fill(0)
135
+ // .map(x => x + 1)
136
+ // .slice(0, 5);
137
+ // ```
138
+ // In this case the depth is 3, and the default value of ignoreChainDeeperThan is 2.
139
+ // So the check can be skipped.
140
+ if ( maxDepth > ignoreChainDeeperThan ) {
110
141
return ;
111
142
}
112
143
113
- const { maxLineLength = 100 } = context . options [ 0 ] ?? { } ;
114
144
const { property} = callee ;
115
145
const lastToken = sourceCode . getLastToken ( node , {
116
146
filter : token => token . loc . end . line === property . loc . start . line ,
0 commit comments