@@ -55,130 +55,6 @@ export default util.createRule<Options, MessageIds>({
55
55
create ( context , [ options ] ) {
56
56
const rules = baseRule . create ( context ) ;
57
57
58
- /**
59
- * Returns whether the node is number literal
60
- * @param node the node literal being evaluated
61
- * @returns true if the node is a number literal
62
- */
63
- function isNumber ( node : TSESTree . Literal ) : boolean {
64
- return typeof node . value === 'number' ;
65
- }
66
-
67
- /**
68
- * Checks if the node grandparent is a Typescript type alias declaration
69
- * @param node the node to be validated.
70
- * @returns true if the node grandparent is a Typescript type alias declaration
71
- * @private
72
- */
73
- function isGrandparentTSTypeAliasDeclaration ( node : TSESTree . Node ) : boolean {
74
- return node . parent && node . parent . parent
75
- ? node . parent . parent . type === AST_NODE_TYPES . TSTypeAliasDeclaration
76
- : false ;
77
- }
78
-
79
- /**
80
- * Checks if the node grandparent is a Typescript union type and its parent is a type alias declaration
81
- * @param node the node to be validated.
82
- * @returns true if the node grandparent is a Typescript union type and its parent is a type alias declaration
83
- * @private
84
- */
85
- function isGrandparentTSUnionType ( node : TSESTree . Node ) : boolean {
86
- if (
87
- node . parent &&
88
- node . parent . parent &&
89
- node . parent . parent . type === AST_NODE_TYPES . TSUnionType
90
- ) {
91
- return isGrandparentTSTypeAliasDeclaration ( node . parent ) ;
92
- }
93
-
94
- return false ;
95
- }
96
-
97
- /**
98
- * Checks if the node parent is a Typescript enum member
99
- * @param node the node to be validated.
100
- * @returns true if the node parent is a Typescript enum member
101
- * @private
102
- */
103
- function isParentTSEnumDeclaration ( node : TSESTree . Node ) : boolean {
104
- return (
105
- typeof node . parent !== 'undefined' &&
106
- node . parent . type === AST_NODE_TYPES . TSEnumMember
107
- ) ;
108
- }
109
-
110
- /**
111
- * Checks if the node parent is a Typescript literal type
112
- * @param node the node to be validated.
113
- * @returns true if the node parent is a Typescript literal type
114
- * @private
115
- */
116
- function isParentTSLiteralType ( node : TSESTree . Node ) : boolean {
117
- return node . parent
118
- ? node . parent . type === AST_NODE_TYPES . TSLiteralType
119
- : false ;
120
- }
121
-
122
- /**
123
- * Checks if the node is a valid TypeScript numeric literal type.
124
- * @param node the node to be validated.
125
- * @returns true if the node is a TypeScript numeric literal type.
126
- * @private
127
- */
128
- function isTSNumericLiteralType ( node : TSESTree . Node ) : boolean {
129
- // For negative numbers, update the parent node
130
- if (
131
- node . parent &&
132
- node . parent . type === AST_NODE_TYPES . UnaryExpression &&
133
- node . parent . operator === '-'
134
- ) {
135
- node = node . parent ;
136
- }
137
-
138
- // If the parent node is not a TSLiteralType, early return
139
- if ( ! isParentTSLiteralType ( node ) ) {
140
- return false ;
141
- }
142
-
143
- // If the grandparent is a TSTypeAliasDeclaration, ignore
144
- if ( isGrandparentTSTypeAliasDeclaration ( node ) ) {
145
- return true ;
146
- }
147
-
148
- // If the grandparent is a TSUnionType and it's parent is a TSTypeAliasDeclaration, ignore
149
- if ( isGrandparentTSUnionType ( node ) ) {
150
- return true ;
151
- }
152
-
153
- return false ;
154
- }
155
-
156
- /**
157
- * Checks if the node parent is a readonly class property
158
- * @param node the node to be validated.
159
- * @returns true if the node parent is a readonly class property
160
- * @private
161
- */
162
- function isParentTSReadonlyClassProperty ( node : TSESTree . Node ) : boolean {
163
- if (
164
- node . parent &&
165
- node . parent . type === AST_NODE_TYPES . UnaryExpression &&
166
- [ '-' , '+' ] . includes ( node . parent . operator )
167
- ) {
168
- node = node . parent ;
169
- }
170
-
171
- if (
172
- node . parent &&
173
- node . parent . type === AST_NODE_TYPES . ClassProperty &&
174
- node . parent . readonly
175
- ) {
176
- return true ;
177
- }
178
-
179
- return false ;
180
- }
181
-
182
58
return {
183
59
Literal ( node ) : void {
184
60
// Check if the node is a TypeScript enum declaration
@@ -189,14 +65,17 @@ export default util.createRule<Options, MessageIds>({
189
65
// Check TypeScript specific nodes for Numeric Literal
190
66
if (
191
67
options . ignoreNumericLiteralTypes &&
192
- isNumber ( node ) &&
68
+ typeof node . value === 'number' &&
193
69
isTSNumericLiteralType ( node )
194
70
) {
195
71
return ;
196
72
}
197
73
198
74
// Check if the node is a readonly class property
199
- if ( isNumber ( node ) && isParentTSReadonlyClassProperty ( node ) ) {
75
+ if (
76
+ typeof node . value === 'number' &&
77
+ isParentTSReadonlyClassProperty ( node )
78
+ ) {
200
79
if ( options . ignoreReadonlyClassProperties ) {
201
80
return ;
202
81
}
@@ -207,8 +86,10 @@ export default util.createRule<Options, MessageIds>({
207
86
let raw = node . raw ;
208
87
209
88
if (
210
- node . parent &&
211
- node . parent . type === AST_NODE_TYPES . UnaryExpression
89
+ node . parent ?. type === AST_NODE_TYPES . UnaryExpression &&
90
+ // the base rule only shows the operator for negative numbers
91
+ // https://github.com/eslint/eslint/blob/9dfc8501fb1956c90dc11e6377b4cb38a6bea65d/lib/rules/no-magic-numbers.js#L126
92
+ node . parent . operator === '-'
212
93
) {
213
94
fullNumberNode = node . parent ;
214
95
raw = `${ node . parent . operator } ${ node . raw } ` ;
@@ -229,3 +110,111 @@ export default util.createRule<Options, MessageIds>({
229
110
} ;
230
111
} ,
231
112
} ) ;
113
+
114
+ /**
115
+ * Gets the true parent of the literal, handling prefixed numbers (-1 / +1)
116
+ */
117
+ function getLiteralParent ( node : TSESTree . Literal ) : TSESTree . Node | undefined {
118
+ if (
119
+ node . parent ?. type === AST_NODE_TYPES . UnaryExpression &&
120
+ [ '-' , '+' ] . includes ( node . parent . operator )
121
+ ) {
122
+ return node . parent . parent ;
123
+ }
124
+
125
+ return node . parent ;
126
+ }
127
+
128
+ /**
129
+ * Checks if the node grandparent is a Typescript type alias declaration
130
+ * @param node the node to be validated.
131
+ * @returns true if the node grandparent is a Typescript type alias declaration
132
+ * @private
133
+ */
134
+ function isGrandparentTSTypeAliasDeclaration ( node : TSESTree . Node ) : boolean {
135
+ return node . parent ?. parent ?. type === AST_NODE_TYPES . TSTypeAliasDeclaration ;
136
+ }
137
+
138
+ /**
139
+ * Checks if the node grandparent is a Typescript union type and its parent is a type alias declaration
140
+ * @param node the node to be validated.
141
+ * @returns true if the node grandparent is a Typescript union type and its parent is a type alias declaration
142
+ * @private
143
+ */
144
+ function isGrandparentTSUnionType ( node : TSESTree . Node ) : boolean {
145
+ if ( node . parent ?. parent ?. type === AST_NODE_TYPES . TSUnionType ) {
146
+ return isGrandparentTSTypeAliasDeclaration ( node . parent ) ;
147
+ }
148
+
149
+ return false ;
150
+ }
151
+
152
+ /**
153
+ * Checks if the node parent is a Typescript enum member
154
+ * @param node the node to be validated.
155
+ * @returns true if the node parent is a Typescript enum member
156
+ * @private
157
+ */
158
+ function isParentTSEnumDeclaration ( node : TSESTree . Literal ) : boolean {
159
+ const parent = getLiteralParent ( node ) ;
160
+ return parent ?. type === AST_NODE_TYPES . TSEnumMember ;
161
+ }
162
+
163
+ /**
164
+ * Checks if the node parent is a Typescript literal type
165
+ * @param node the node to be validated.
166
+ * @returns true if the node parent is a Typescript literal type
167
+ * @private
168
+ */
169
+ function isParentTSLiteralType ( node : TSESTree . Node ) : boolean {
170
+ return node . parent ?. type === AST_NODE_TYPES . TSLiteralType ;
171
+ }
172
+
173
+ /**
174
+ * Checks if the node is a valid TypeScript numeric literal type.
175
+ * @param node the node to be validated.
176
+ * @returns true if the node is a TypeScript numeric literal type.
177
+ * @private
178
+ */
179
+ function isTSNumericLiteralType ( node : TSESTree . Node ) : boolean {
180
+ // For negative numbers, use the parent node
181
+ if (
182
+ node . parent ?. type === AST_NODE_TYPES . UnaryExpression &&
183
+ node . parent . operator === '-'
184
+ ) {
185
+ node = node . parent ;
186
+ }
187
+
188
+ // If the parent node is not a TSLiteralType, early return
189
+ if ( ! isParentTSLiteralType ( node ) ) {
190
+ return false ;
191
+ }
192
+
193
+ // If the grandparent is a TSTypeAliasDeclaration, ignore
194
+ if ( isGrandparentTSTypeAliasDeclaration ( node ) ) {
195
+ return true ;
196
+ }
197
+
198
+ // If the grandparent is a TSUnionType and it's parent is a TSTypeAliasDeclaration, ignore
199
+ if ( isGrandparentTSUnionType ( node ) ) {
200
+ return true ;
201
+ }
202
+
203
+ return false ;
204
+ }
205
+
206
+ /**
207
+ * Checks if the node parent is a readonly class property
208
+ * @param node the node to be validated.
209
+ * @returns true if the node parent is a readonly class property
210
+ * @private
211
+ */
212
+ function isParentTSReadonlyClassProperty ( node : TSESTree . Literal ) : boolean {
213
+ const parent = getLiteralParent ( node ) ;
214
+
215
+ if ( parent ?. type === AST_NODE_TYPES . ClassProperty && parent . readonly ) {
216
+ return true ;
217
+ }
218
+
219
+ return false ;
220
+ }
0 commit comments