1
+ import {
2
+ TSESTree ,
3
+ AST_NODE_TYPES ,
4
+ } from '@typescript-eslint/experimental-utils' ;
1
5
import * as util from '../util' ;
2
6
3
7
export default util . createRule ( {
@@ -12,12 +16,145 @@ export default util.createRule({
12
16
messages : {
13
17
unexpectedAny : 'Unexpected any. Specify a different type.' ,
14
18
} ,
15
- schema : [ ] ,
19
+ schema : [
20
+ {
21
+ type : 'object' ,
22
+ additionalProperties : false ,
23
+ properties : {
24
+ ignoreRestArgs : {
25
+ type : 'boolean' ,
26
+ } ,
27
+ } ,
28
+ } ,
29
+ ] ,
16
30
} ,
17
- defaultOptions : [ ] ,
18
- create ( context ) {
31
+ defaultOptions : [
32
+ {
33
+ ignoreRestArgs : false ,
34
+ } ,
35
+ ] ,
36
+ create ( context , [ { ignoreRestArgs } ] ) {
37
+ /**
38
+ * Checks if the node is an arrow function, function declaration or function expression
39
+ * @param node the node to be validated.
40
+ * @returns true if the node is an arrow function, function declaration or function expression
41
+ * @private
42
+ */
43
+ function isNodeValidFunction ( node : TSESTree . Node ) : boolean {
44
+ return [
45
+ AST_NODE_TYPES . ArrowFunctionExpression ,
46
+ AST_NODE_TYPES . FunctionDeclaration ,
47
+ AST_NODE_TYPES . FunctionExpression ,
48
+ ] . includes ( node . type ) ;
49
+ }
50
+
51
+ /**
52
+ * Checks if the node is a rest element child node of a function
53
+ * @param node the node to be validated.
54
+ * @returns true if the node is a rest element child node of a function
55
+ * @private
56
+ */
57
+ function isNodeRestElementInFunction ( node : TSESTree . Node ) : boolean {
58
+ return (
59
+ node . type === AST_NODE_TYPES . RestElement &&
60
+ typeof node . parent !== 'undefined' &&
61
+ isNodeValidFunction ( node . parent )
62
+ ) ;
63
+ }
64
+
65
+ /**
66
+ * Checks if the node is a TSTypeOperator node with a readonly operator
67
+ * @param node the node to be validated.
68
+ * @returns true if the node is a TSTypeOperator node with a readonly operator
69
+ * @private
70
+ */
71
+ function isNodeReadonlyTSTypeOperator ( node : TSESTree . Node ) : boolean {
72
+ return (
73
+ node . type === AST_NODE_TYPES . TSTypeOperator &&
74
+ node . operator === 'readonly'
75
+ ) ;
76
+ }
77
+
78
+ /**
79
+ * Checks if the node is a TSTypeReference node with an Array identifier
80
+ * @param node the node to be validated.
81
+ * @returns true if the node is a TSTypeReference node with an Array identifier
82
+ * @private
83
+ */
84
+ function isNodeValidArrayTSTypeReference ( node : TSESTree . Node ) : boolean {
85
+ return (
86
+ node . type === AST_NODE_TYPES . TSTypeReference &&
87
+ typeof node . typeName !== 'undefined' &&
88
+ node . typeName . type === AST_NODE_TYPES . Identifier &&
89
+ [ 'Array' , 'ReadonlyArray' ] . includes ( node . typeName . name )
90
+ ) ;
91
+ }
92
+
93
+ /**
94
+ * Checks if the node is a valid TSTypeOperator or TSTypeReference node
95
+ * @param node the node to be validated.
96
+ * @returns true if the node is a valid TSTypeOperator or TSTypeReference node
97
+ * @private
98
+ */
99
+ function isNodeValidTSType ( node : TSESTree . Node ) : boolean {
100
+ return (
101
+ isNodeReadonlyTSTypeOperator ( node ) ||
102
+ isNodeValidArrayTSTypeReference ( node )
103
+ ) ;
104
+ }
105
+
106
+ /**
107
+ * Checks if the great grand-parent node is a RestElement node in a function
108
+ * @param node the node to be validated.
109
+ * @returns true if the great grand-parent node is a RestElement node in a function
110
+ * @private
111
+ */
112
+ function isGreatGrandparentRestElement ( node : TSESTree . Node ) : boolean {
113
+ return (
114
+ typeof node . parent !== 'undefined' &&
115
+ typeof node . parent . parent !== 'undefined' &&
116
+ typeof node . parent . parent . parent !== 'undefined' &&
117
+ isNodeRestElementInFunction ( node . parent . parent . parent )
118
+ ) ;
119
+ }
120
+
121
+ /**
122
+ * Checks if the great great grand-parent node is a valid RestElement node in a function
123
+ * @param node the node to be validated.
124
+ * @returns true if the great great grand-parent node is a valid RestElement node in a function
125
+ * @private
126
+ */
127
+ function isGreatGreatGrandparentRestElement ( node : TSESTree . Node ) : boolean {
128
+ return (
129
+ typeof node . parent !== 'undefined' &&
130
+ typeof node . parent . parent !== 'undefined' &&
131
+ isNodeValidTSType ( node . parent . parent ) &&
132
+ typeof node . parent . parent . parent !== 'undefined' &&
133
+ typeof node . parent . parent . parent . parent !== 'undefined' &&
134
+ isNodeRestElementInFunction ( node . parent . parent . parent . parent )
135
+ ) ;
136
+ }
137
+
138
+ /**
139
+ * Checks if the great grand-parent or the great great grand-parent node is a RestElement node
140
+ * @param node the node to be validated.
141
+ * @returns true if the great grand-parent or the great great grand-parent node is a RestElement node
142
+ * @private
143
+ */
144
+ function isNodeDescendantOfRestElementInFunction (
145
+ node : TSESTree . Node ,
146
+ ) : boolean {
147
+ return (
148
+ isGreatGrandparentRestElement ( node ) ||
149
+ isGreatGreatGrandparentRestElement ( node )
150
+ ) ;
151
+ }
152
+
19
153
return {
20
154
TSAnyKeyword ( node ) {
155
+ if ( ignoreRestArgs && isNodeDescendantOfRestElementInFunction ( node ) ) {
156
+ return ;
157
+ }
21
158
context . report ( {
22
159
node,
23
160
messageId : 'unexpectedAny' ,
0 commit comments