eslint-plugin-constructors 1.1.1 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -57
- package/package.json +5 -3
- package/src/data/deprecations.js +3 -0
- package/src/index.js +10 -6
- package/src/rules/no-explicit-return.js +2 -2
- package/src/rules/require-error-subclass-name.js +5 -5
- package/src/rules/require-new.js +45 -13
package/README.md
CHANGED
|
@@ -10,6 +10,8 @@ ESLint rules to enforce best practices for constructor usage.
|
|
|
10
10
|
|
|
11
11
|
<img src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-constructors/6eeba7b2cb/assets/images/screenshots/vs-code/squiggles.png">
|
|
12
12
|
|
|
13
|
+
---
|
|
14
|
+
|
|
13
15
|
## Installation
|
|
14
16
|
|
|
15
17
|
From your project root:
|
|
@@ -18,7 +20,14 @@ From your project root:
|
|
|
18
20
|
npm i -D eslint-plugin-constructors
|
|
19
21
|
```
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
<h2 id="usage">
|
|
26
|
+
Usage
|
|
27
|
+
<a title="Copy section URL" target="_blank"
|
|
28
|
+
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-constructors%2F%23usage">
|
|
29
|
+
<img height=17 width=22 alt="[Copy section URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="bottom"></a>
|
|
30
|
+
</h2>
|
|
22
31
|
|
|
23
32
|
Add `constructors` to your flat config:
|
|
24
33
|
|
|
@@ -32,7 +41,7 @@ export default [
|
|
|
32
41
|
rules: {
|
|
33
42
|
'constructors/no-explicit-return': 'error',
|
|
34
43
|
'constructors/require-error-subclass-name': 'error',
|
|
35
|
-
'constructors/require-new': ['error', '
|
|
44
|
+
'constructors/require-new': ['error', 'errors']
|
|
36
45
|
}
|
|
37
46
|
}
|
|
38
47
|
]
|
|
@@ -53,44 +62,65 @@ export default [
|
|
|
53
62
|
]
|
|
54
63
|
```
|
|
55
64
|
|
|
56
|
-
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
<h2 id="supported-rules">
|
|
68
|
+
Supported rules
|
|
69
|
+
<a title="Copy section URL" target="_blank"
|
|
70
|
+
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-constructors%2F%23supported-rules">
|
|
71
|
+
<img height=17 width=22 alt="[Copy section URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="bottom"></a>
|
|
72
|
+
</h2>
|
|
57
73
|
|
|
58
74
|
| ID | Description | Auto-fixable | Recommended |
|
|
59
75
|
| --- | --- | :-: | :-: |
|
|
60
76
|
| [`no-explicit-return`](#no-explicit-return) | Disallows explicit `return` statements in class constructors | ❌ | ✅ |
|
|
61
77
|
| [`require-error-subclass-name`](#require-error-subclass-name) | Requires classes extending `Error` to have names ending in `Error` | ❌ | ✅ |
|
|
62
|
-
| [`require-new`](#require-new
|
|
78
|
+
| [`require-new`](#require-new) | Requires `new` when calling error constructors | ✅ | ✅ |
|
|
63
79
|
|
|
64
80
|
---
|
|
65
81
|
|
|
66
|
-
|
|
82
|
+
<h3 id="no-explicit-return">
|
|
83
|
+
<code>no-explicit-return</code>
|
|
84
|
+
<a title="Included in recommended config" href="#usage">
|
|
85
|
+
<img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
|
|
86
|
+
<a title="Copy rule URL" target="_blank"
|
|
87
|
+
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-constructors%2F%23no-explicit-return">
|
|
88
|
+
<img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
|
|
89
|
+
</h3>
|
|
67
90
|
|
|
68
91
|
> Disallows explicit `return` statements inside class constructors.
|
|
69
92
|
|
|
70
93
|
#### Incorrect code
|
|
71
94
|
|
|
72
|
-
```
|
|
73
|
-
class A {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
class B {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
95
|
+
```diff
|
|
96
|
+
class A {
|
|
97
|
+
constructor() {
|
|
98
|
+
! return
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
class B {
|
|
103
|
+
constructor() {
|
|
104
|
+
! return this
|
|
105
|
+
}
|
|
106
|
+
}
|
|
84
107
|
```
|
|
85
108
|
|
|
86
109
|
#### Correct code
|
|
87
110
|
|
|
88
|
-
```
|
|
89
|
-
class A {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
111
|
+
```diff
|
|
112
|
+
class A {
|
|
113
|
+
constructor() {
|
|
114
|
+
- return
|
|
115
|
+
+ this.x = 1
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
class B {
|
|
119
|
+
constructor() {
|
|
120
|
+
- return this
|
|
121
|
+
+ this.x = 1
|
|
122
|
+
}
|
|
123
|
+
}
|
|
94
124
|
```
|
|
95
125
|
|
|
96
126
|
#### When not to use it
|
|
@@ -105,22 +135,31 @@ If you need to return a different object from a constructor.
|
|
|
105
135
|
|
|
106
136
|
---
|
|
107
137
|
|
|
108
|
-
|
|
138
|
+
<h3 id="require-error-subclass-name">
|
|
139
|
+
<code>require-error-subclass-name</code>
|
|
140
|
+
<a title="Included in recommended config" href="#usage">
|
|
141
|
+
<img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
|
|
142
|
+
<a title="Copy rule URL" target="_blank"
|
|
143
|
+
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-constructors%2F%23require-error-subclass-name">
|
|
144
|
+
<img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
|
|
145
|
+
</h3>
|
|
109
146
|
|
|
110
147
|
> Requires classes extending `Error` have a name ending in `Error`.
|
|
111
148
|
|
|
112
149
|
#### Incorrect code
|
|
113
150
|
|
|
114
|
-
```
|
|
115
|
-
class My extends Error {}
|
|
116
|
-
const Custom = class extends Error {}
|
|
151
|
+
```diff
|
|
152
|
+
! class My extends Error {}
|
|
153
|
+
! const Custom = class extends Error {}
|
|
117
154
|
```
|
|
118
155
|
|
|
119
156
|
#### Correct code
|
|
120
157
|
|
|
121
|
-
```
|
|
122
|
-
class
|
|
123
|
-
const
|
|
158
|
+
```diff
|
|
159
|
+
- class My extends Error {}
|
|
160
|
+
- const Custom = class extends Error {}
|
|
161
|
+
+ class MyError extends Error {}
|
|
162
|
+
+ const CustomError = class extends Error {}
|
|
124
163
|
```
|
|
125
164
|
|
|
126
165
|
#### When not to use it
|
|
@@ -135,40 +174,59 @@ If you don't follow the convention of suffixing custom error classes w/ `Error`.
|
|
|
135
174
|
|
|
136
175
|
---
|
|
137
176
|
|
|
138
|
-
|
|
177
|
+
<h3 id="require-new">
|
|
178
|
+
<code>require-new</code>
|
|
179
|
+
<a title="Included in recommended config" href="#usage">
|
|
180
|
+
<img height=18 alt="[Recommended]" src="https://img.shields.io/badge/Recommended-f1f20a?style=flat-square" align="middle"></a>
|
|
181
|
+
<a title="Accepts eslint --fix" target="_blank" href="https://eslint.org/docs/latest/use/command-line-interface#--fix">
|
|
182
|
+
<img height=18 alt="[Auto-fixable]" src="https://img.shields.io/badge/Auto--fixable-e8357a?style=flat-square" align="middle"></a>
|
|
183
|
+
<a title="Copy rule URL" target="_blank"
|
|
184
|
+
href="https://copy-to-clipboard.onrender.com/copy/https%3A%2F%2Fcodeberg.org%2Fadamlui%2Feslint-plugin-constructors%2F%23require-new">
|
|
185
|
+
<img height=16 width=21 alt="[Copy rule URL]" src="https://api.iconify.design/mdi/content-copy.svg?color=%23cccccc" align="middle"></a>
|
|
186
|
+
</h3>
|
|
139
187
|
|
|
140
|
-
> Requires `new` when calling error constructors (and optionally other built-
|
|
188
|
+
> Requires `new` when calling error constructors (and optionally other built-ins).
|
|
141
189
|
|
|
142
190
|
#### Options
|
|
143
191
|
|
|
144
|
-
- `'
|
|
145
|
-
- `'
|
|
192
|
+
- `'errors'` (default) — require for error constructors.
|
|
193
|
+
- `'throwing'` — require for errors + constructors that throw a `TypeError` when called without `new`.
|
|
194
|
+
- `'all'` — require for errors + throwing constructors + constructors where `new` is optional.
|
|
195
|
+
|
|
196
|
+
Excluded: `Boolean`, `Number`, `String` (calling w/ `new` returns wrapper objects), and `Symbol`, `BigInt` (cannot be called w/ `new`).
|
|
146
197
|
|
|
147
198
|
#### Incorrect code
|
|
148
199
|
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
throw
|
|
200
|
+
```diff
|
|
201
|
+
/* eslint constructors/require-new: ['error', 'errors'] */
|
|
202
|
+
! throw Error('boom')
|
|
152
203
|
|
|
153
|
-
|
|
154
|
-
const
|
|
155
|
-
|
|
204
|
+
/* eslint constructors/require-new: ['error', 'throwing'] */
|
|
205
|
+
! const m = Map()
|
|
206
|
+
|
|
207
|
+
/* eslint constructors/require-new: ['error', 'all'] */
|
|
208
|
+
! const arr = Array()
|
|
156
209
|
```
|
|
157
210
|
|
|
158
211
|
#### Correct code
|
|
159
212
|
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
throw
|
|
213
|
+
```diff
|
|
214
|
+
/* eslint constructors/require-new: ['error', 'errors'] */
|
|
215
|
+
- throw Error('boom')
|
|
216
|
+
+ throw new Error('boom')
|
|
217
|
+
|
|
218
|
+
/* eslint constructors/require-new: ['error', 'throwing'] */
|
|
219
|
+
- const m = Map()
|
|
220
|
+
+ const m = new Map()
|
|
163
221
|
|
|
164
|
-
|
|
165
|
-
const arr =
|
|
166
|
-
|
|
222
|
+
/* eslint constructors/require-new: ['error', 'all'] */
|
|
223
|
+
- const arr = Array()
|
|
224
|
+
+ const arr = new Array()
|
|
167
225
|
```
|
|
168
226
|
|
|
169
227
|
#### When not to use it
|
|
170
228
|
|
|
171
|
-
If you prefer
|
|
229
|
+
If you prefer calling built-ins w/o `new` (which the runtime allows for some of them) and don't want to enforce it for consistency.
|
|
172
230
|
|
|
173
231
|
<div align="center">
|
|
174
232
|
|
|
@@ -178,35 +236,33 @@ If you prefer the convenience of calling built-ins without `new` (which is allow
|
|
|
178
236
|
|
|
179
237
|
---
|
|
180
238
|
|
|
181
|
-
## Shield
|
|
239
|
+
## Shield embed
|
|
182
240
|
|
|
183
241
|
<a href="https://codeberg.org/adamlui/eslint-plugin-constructors/#readme">
|
|
184
|
-
<img height=32 alt="[Linted by eslint-plugin-constructors]" src="https://img.shields.io/badge/Linted_by-eslint--plugin--constructors-
|
|
242
|
+
<img height=32 alt="[Linted by eslint-plugin-constructors]" src="https://img.shields.io/badge/Linted_by-eslint--plugin--constructors-black?logo=eslint&logoColor=white&labelColor=4B32C3&style=for-the-badge"></a>
|
|
185
243
|
|
|
186
244
|
#### HTML
|
|
187
245
|
|
|
188
246
|
```html
|
|
189
247
|
<a href="https://codeberg.org/adamlui/eslint-plugin-constructors/#readme">
|
|
190
|
-
<img height=32 alt="[Linted by eslint-plugin-constructors]" src="https://img.shields.io/badge/Linted_by-eslint--plugin--constructors-
|
|
248
|
+
<img height=32 alt="[Linted by eslint-plugin-constructors]" src="https://img.shields.io/badge/Linted_by-eslint--plugin--constructors-black?logo=eslint&logoColor=white&labelColor=4B32C3&style=for-the-badge"></a>
|
|
191
249
|
```
|
|
192
250
|
|
|
193
251
|
#### Markdown
|
|
194
252
|
|
|
195
253
|
```md
|
|
196
|
-
[](https://codeberg.org/adamlui/eslint-plugin-constructors/#readme)
|
|
197
255
|
```
|
|
198
256
|
|
|
257
|
+
---
|
|
258
|
+
|
|
199
259
|
## License
|
|
200
260
|
|
|
201
261
|
[<img height=62 src="https://cdn.staticdelivr.com/gl/adamlui/eslint-plugin-constructors/af5fe76586/assets/images/logos/mit-license/red-pixelated.png">][epc-license]
|
|
202
262
|
|
|
203
263
|
<details>
|
|
204
264
|
|
|
205
|
-
<summary>
|
|
206
|
-
|
|
207
|
-
Copyright © 2026 [Adam Lui][adamlui-cb] under the [MIT license][epc-license].
|
|
208
|
-
|
|
209
|
-
</summary><br>
|
|
265
|
+
<summary>Copyright © 2026 <a href="https://codeberg.org/adamlui"><b>Adam Lui</b></a> under the <a href="https://codeberg.org/adamlui/eslint-plugin-constructors/src/branch/main/docs/LICENSE.md"><b>MIT license</b></a>.</summary><br>
|
|
210
266
|
|
|
211
267
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
212
268
|
|
|
@@ -216,6 +272,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|
|
216
272
|
|
|
217
273
|
</details>
|
|
218
274
|
|
|
275
|
+
---
|
|
276
|
+
|
|
219
277
|
## Related
|
|
220
278
|
|
|
221
279
|
<!-- eslint-plugin-greasemonkey -->
|
|
@@ -249,7 +307,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|
|
249
307
|
|
|
250
308
|
<!-- Links -->
|
|
251
309
|
|
|
252
|
-
[adamlui-cb]: https://codeberg.org/adamlui
|
|
253
310
|
[adamlui-npmx]: https://npmx.dev/org/adamlui
|
|
254
311
|
[epc-bugs]: https://codeberg.org/adamlui/eslint-plugin-constructors/issues/new
|
|
255
312
|
[epc-license]: https://codeberg.org/adamlui/eslint-plugin-constructors/src/branch/main/docs/LICENSE.md
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-constructors",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "ESLint rules for constructor usage",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"lint:fix": "eslint . --fix --cache && yamllint .",
|
|
41
41
|
"lint:fix-all": "eslint . --fix && yamllint .",
|
|
42
42
|
"test": "node tests/run.js",
|
|
43
|
-
"demo": "
|
|
43
|
+
"demo": "node demo/run.js",
|
|
44
44
|
"bump:patch": "bash utils/bump.sh patch",
|
|
45
45
|
"bump:minor": "bash utils/bump.sh minor",
|
|
46
46
|
"bump:feat": "npm run bump:minor",
|
|
@@ -59,6 +59,9 @@
|
|
|
59
59
|
"eslintplugin",
|
|
60
60
|
"security"
|
|
61
61
|
],
|
|
62
|
+
"dependencies": {
|
|
63
|
+
"globals": "^17.12.0"
|
|
64
|
+
},
|
|
62
65
|
"peerDependencies": {
|
|
63
66
|
"eslint": ">=9.0.0"
|
|
64
67
|
},
|
|
@@ -77,7 +80,6 @@
|
|
|
77
80
|
"eslint-plugin-promise": "^7.3.0",
|
|
78
81
|
"eslint-plugin-regexp": "^3.3.0",
|
|
79
82
|
"eslint-plugin-security": "^4.0.1",
|
|
80
|
-
"globals": "^17.12.0",
|
|
81
83
|
"husky": "^9.1.7",
|
|
82
84
|
"yamllint-js": "^0.2.4"
|
|
83
85
|
}
|
package/src/index.js
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
|
-
import requireNew from './rules/require-new.js'
|
|
2
|
-
import requireErrorSubclassName from './rules/require-error-subclass-name.js'
|
|
3
1
|
import noExplicitReturn from './rules/no-explicit-return.js'
|
|
2
|
+
import requireErrorSubclassName from './rules/require-error-subclass-name.js'
|
|
3
|
+
import requireNew from './rules/require-new.js'
|
|
4
4
|
|
|
5
5
|
const plugin = {
|
|
6
6
|
rules: {
|
|
7
|
-
'
|
|
7
|
+
'no-explicit-return': noExplicitReturn,
|
|
8
8
|
'require-error-subclass-name': requireErrorSubclassName,
|
|
9
|
-
'
|
|
9
|
+
'require-new': requireNew
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
const docsURL = 'https://codeberg.org/adamlui/eslint-plugin-constructors/#'
|
|
14
|
+
for (const [ruleId, rule] of Object.entries(plugin.rules))
|
|
15
|
+
rule.meta.docs.url = `${docsURL}${ruleId}${ rule.meta.fixable ? '-auto-fixable' : '' }`
|
|
16
|
+
|
|
13
17
|
plugin.configs = {
|
|
14
18
|
recommended: {
|
|
15
19
|
plugins: { constructors: plugin },
|
|
16
20
|
rules: {
|
|
17
|
-
'constructors/
|
|
21
|
+
'constructors/no-explicit-return': 'error',
|
|
18
22
|
'constructors/require-error-subclass-name': 'error',
|
|
19
|
-
'constructors/
|
|
23
|
+
'constructors/require-new': 'error'
|
|
20
24
|
}
|
|
21
25
|
}
|
|
22
26
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
const
|
|
1
|
+
const re = { funcNodeType: /^(?:Arrow)?Function(?:Declaration|Expression)$/ }
|
|
2
2
|
|
|
3
3
|
function isInsideConstructorFunc(node) {
|
|
4
4
|
let current = node.parent
|
|
5
5
|
while (current) {
|
|
6
|
-
if (
|
|
6
|
+
if (re.funcNodeType.test(current.type))
|
|
7
7
|
return ( // whether this func is constructor's val
|
|
8
8
|
current.parent?.type == 'MethodDefinition'
|
|
9
9
|
&& current.parent.kind == 'constructor'
|
|
@@ -11,16 +11,16 @@ export default {
|
|
|
11
11
|
},
|
|
12
12
|
|
|
13
13
|
create(context) {
|
|
14
|
-
function checkName(name, node) {
|
|
15
|
-
if (!name || name.endsWith('Error')) return
|
|
16
|
-
context.report({ node, messageId: 'endWithError' })
|
|
17
|
-
}
|
|
18
|
-
|
|
19
14
|
function checkClassNode(node) {
|
|
20
15
|
if (!node.id || !node.superClass?.name?.endsWith('Error')) return
|
|
21
16
|
checkName(node.id.name, node.id)
|
|
22
17
|
}
|
|
23
18
|
|
|
19
|
+
function checkName(name, node) {
|
|
20
|
+
if (!name || name.endsWith('Error')) return
|
|
21
|
+
context.report({ node, messageId: 'endWithError' })
|
|
22
|
+
}
|
|
23
|
+
|
|
24
24
|
function checkVariableDeclarator(node) {
|
|
25
25
|
const classExpr = node.init
|
|
26
26
|
if (classExpr?.type != 'ClassExpression'
|
package/src/rules/require-new.js
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import deprecations from '../data/deprecations.js'
|
|
2
|
+
import globals from 'globals'
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const errorConstructors = new Set(Object.keys(globals.builtin).filter(name => name.endsWith('Error')))
|
|
5
|
+
|
|
6
|
+
const throwingConstructors = new Set([
|
|
7
|
+
'ArrayBuffer', 'BigInt64Array', 'BigUint64Array', 'DataView', 'FinalizationRegistry', 'Float32Array',
|
|
8
|
+
'Float64Array', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Promise', 'Proxy', 'Set', 'SharedArrayBuffer',
|
|
9
|
+
'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', 'WeakRef', 'WeakSet'
|
|
10
|
+
])
|
|
11
|
+
|
|
12
|
+
const lenientConstructors = new Set(['Array', 'Date', 'Function', 'Object', 'RegExp'])
|
|
13
|
+
|
|
14
|
+
const legacyBuiltins = new Set([
|
|
5
15
|
'Array', 'BigInt', 'Boolean', 'Date', 'Function', 'Map', 'Number', 'Object', 'RegExp', 'Set', 'String', 'Symbol',
|
|
6
16
|
'WeakMap', 'WeakSet'
|
|
7
17
|
])
|
|
8
18
|
|
|
9
|
-
function isErrConstructor(name) { return errors.has(name) }
|
|
10
|
-
|
|
11
19
|
export default {
|
|
12
20
|
meta: {
|
|
13
21
|
type: 'problem',
|
|
@@ -19,22 +27,46 @@ export default {
|
|
|
19
27
|
fixable: 'code',
|
|
20
28
|
schema: [{
|
|
21
29
|
type: 'string',
|
|
22
|
-
enum: ['error-only', 'builtins'],
|
|
23
|
-
description: 'Constructor categories to check
|
|
30
|
+
enum: ['errors', 'throwing', 'all', 'error-only', 'builtins'],
|
|
31
|
+
description: 'Constructor categories to check'
|
|
24
32
|
}],
|
|
25
|
-
defaultOptions: ['
|
|
26
|
-
messages: {
|
|
33
|
+
defaultOptions: ['errors'],
|
|
34
|
+
messages: {
|
|
35
|
+
requireNew: 'Use `new {{name}}()` instead of `{{name}}()`',
|
|
36
|
+
deprecatedMode: `'{{old}}' is deprecated. Use '{{new}}' instead.`
|
|
37
|
+
}
|
|
27
38
|
},
|
|
28
39
|
|
|
29
40
|
create(context) {
|
|
30
|
-
const
|
|
41
|
+
const optionAliases = deprecations.options['require-new'] || {},
|
|
42
|
+
rawMode = context.options[0] || 'errors'
|
|
43
|
+
/* eslint-disable security/detect-object-injection */
|
|
44
|
+
let mode = optionAliases[rawMode] || rawMode, deprecation
|
|
45
|
+
if (optionAliases[rawMode])
|
|
46
|
+
deprecation = { old: rawMode, new: optionAliases[rawMode] }
|
|
47
|
+
/* eslint-enable security/detect-object-injection */
|
|
48
|
+
else if (rawMode == 'builtins')
|
|
49
|
+
mode = 'legacy-builtins'
|
|
50
|
+
|
|
51
|
+
function shouldReportName(name) {
|
|
52
|
+
return mode == 'errors' ? errorConstructors.has(name)
|
|
53
|
+
: mode == 'throwing' ? errorConstructors.has(name) || throwingConstructors.has(name)
|
|
54
|
+
: mode == 'all' ? errorConstructors.has(name) || throwingConstructors.has(name)
|
|
55
|
+
|| lenientConstructors.has(name)
|
|
56
|
+
: mode == 'legacy-builtins' ? errorConstructors.has(name) || legacyBuiltins.has(name)
|
|
57
|
+
: false
|
|
58
|
+
}
|
|
59
|
+
|
|
31
60
|
return {
|
|
61
|
+
Program(node) {
|
|
62
|
+
if (deprecation)
|
|
63
|
+
context.report({
|
|
64
|
+
node, messageId: 'deprecatedMode', data: { old: deprecation.old, new: deprecation.new }})
|
|
65
|
+
},
|
|
32
66
|
CallExpression(node) {
|
|
33
67
|
if (node.new) return
|
|
34
68
|
const calleeName = node.callee.name ; if (!calleeName) return
|
|
35
|
-
|
|
36
|
-
: isErrConstructor(calleeName) || builtins.has(calleeName)
|
|
37
|
-
if (shouldReport)
|
|
69
|
+
if (shouldReportName(calleeName))
|
|
38
70
|
context.report({
|
|
39
71
|
node, messageId: 'requireNew', data: { name: calleeName },
|
|
40
72
|
fix(fixer) { return fixer.insertTextBefore(node, 'new ') }
|