Skip to content

Commit 3af50b7

Browse files
authored
feat(rule): add no-new-statics rule (#82)
Resolves #75
1 parent 0f8e861 commit 3af50b7

File tree

7 files changed

+107
-2
lines changed

7 files changed

+107
-2
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ Then configure the rules you want to use under the rules section.
6161
"promise/no-promise-in-callback": "warn",
6262
"promise/no-callback-in-promise": "warn",
6363
"promise/avoid-new": "warn",
64+
"promise/no-new-statics": "error",
6465
"promise/no-return-in-finally": "warn"
6566
}
6667
}
@@ -87,6 +88,7 @@ or start with the recommended rule set
8788
| [`no-promise-in-callback`][no-promise-in-callback] | Avoid using promises inside of callbacks | :warning: | |
8889
| [`no-callback-in-promise`][no-callback-in-promise] | Avoid calling `cb()` inside of a `then()` (use [nodeify][] instead) | :warning: | |
8990
| [`avoid-new` ][avoid-new] | Avoid creating `new` promises outside of utility libs (use [pify][] instead) | :warning: | |
91+
| [`no-new-statics`][no-new-statics] | Avoid calling `new` on a Promise static method | :bangbang: | |
9092
| [`no-return-in-finally`][no-return-in-finally] | Disallow return statements in `finally()` | :warning: | |
9193
| [`prefer-await-to-then`][prefer-await-to-then] | Prefer `await` to `then()` for reading Promise values | :seven: | |
9294
| [`prefer-await-to-callbacks`][prefer-await-to-callbacks] | Prefer async/await to the callback pattern | :seven: | |
@@ -119,6 +121,7 @@ or start with the recommended rule set
119121
[no-promise-in-callback]: docs/rules/no-promise-in-callback.md
120122
[no-callback-in-promise]: docs/rules/no-callback-in-promise.md
121123
[avoid-new]: docs/rules/avoid-new.md
124+
[no-new-statics]: docs/rules/no-new-statics.md
122125
[no-return-in-finally]: docs/rules/no-return-in-finally.md
123126
[prefer-await-to-then]: docs/rules/prefer-await-to-then.md
124127
[prefer-await-to-callbacks]: docs/rules/prefer-await-to-callbacks.md

__tests__/no-new-statics.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use strict'
2+
3+
const rule = require('../rules/no-new-statics')
4+
const RuleTester = require('eslint').RuleTester
5+
const ruleTester = new RuleTester()
6+
7+
ruleTester.run('no-new-statics', rule, {
8+
valid: [
9+
'Promise.resolve()',
10+
'Promise.reject()',
11+
'Promise.all()',
12+
'Promise.race()',
13+
'new Promise(function (resolve, reject) {})',
14+
'new SomeClass()',
15+
'SomeClass.resolve()',
16+
'new SomeClass.resolve()'
17+
],
18+
invalid: [
19+
{
20+
code: 'new Promise.resolve()',
21+
errors: [{ message: "Avoid calling 'new' on 'Promise.resolve()'" }]
22+
},
23+
{
24+
code: 'new Promise.reject()',
25+
errors: [{ message: "Avoid calling 'new' on 'Promise.reject()'" }]
26+
},
27+
{
28+
code: 'new Promise.all()',
29+
errors: [{ message: "Avoid calling 'new' on 'Promise.all()'" }]
30+
},
31+
{
32+
code: 'new Promise.race()',
33+
errors: [{ message: "Avoid calling 'new' on 'Promise.race()'" }]
34+
}
35+
]
36+
})

docs/rules/no-new-statics.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Avoid calling `new` on a Promise static method (no-new-statics)
2+
3+
Calling a Promise static method with `new` is invalid, resulting in a
4+
`TypeError` at runtime.
5+
6+
## Rule Details
7+
8+
This rule is aimed at flagging instances where a Promise static method is called
9+
with `new`.
10+
11+
Examples for **incorrect** code for this rule:
12+
13+
```js
14+
new Promise.resolve(value)
15+
new Promise.reject(error)
16+
new Promise.race([p1, p2])
17+
new Promise.all([p1, p2])
18+
```
19+
20+
Examples for **correct** code for this rule:
21+
22+
```js
23+
Promise.resolve(value)
24+
Promise.reject(error)
25+
Promise.race([p1, p2])
26+
Promise.all([p1, p2])
27+
```
28+
29+
## When Not To Use It
30+
31+
If you do not want to be notified when calling `new` on a Promise static method,
32+
you can safely disable this rule.

index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module.exports = {
1313
'no-promise-in-callback': require('./rules/no-promise-in-callback'),
1414
'no-nesting': require('./rules/no-nesting'),
1515
'avoid-new': require('./rules/avoid-new'),
16+
'no-new-statics': require('./rules/no-new-statics'),
1617
'no-return-in-finally': require('./rules/no-return-in-finally')
1718
},
1819
rulesConfig: {
@@ -34,6 +35,7 @@ module.exports = {
3435
'promise/no-promise-in-callback': 'warn',
3536
'promise/no-callback-in-promise': 'warn',
3637
'promise/avoid-new': 'warn',
38+
'promise/no-new-statics': 'error',
3739
'promise/no-return-in-finally': 'warn'
3840
}
3941
}

rules/lib/is-promise.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55
'use strict'
66

7-
const STATIC_METHODS = ['all', 'race', 'reject', 'resolve']
7+
const PROMISE_STATICS = require('./promise-statics')
88

99
function isPromise(expression) {
1010
return (
@@ -29,7 +29,7 @@ function isPromise(expression) {
2929
expression.callee.type === 'MemberExpression' &&
3030
expression.callee.object.type === 'Identifier' &&
3131
expression.callee.object.name === 'Promise' &&
32-
STATIC_METHODS.indexOf(expression.callee.property.name) !== -1)
32+
PROMISE_STATICS.indexOf(expression.callee.property.name) !== -1)
3333
)
3434
}
3535

rules/lib/promise-statics.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict'
2+
3+
module.exports = ['all', 'race', 'reject', 'resolve']

rules/no-new-statics.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict'
2+
3+
const PROMISE_STATICS = require('./lib/promise-statics')
4+
const getDocsUrl = require('./lib/get-docs-url')
5+
6+
module.exports = {
7+
meta: {
8+
docs: {
9+
url: getDocsUrl('no-new-statics')
10+
}
11+
},
12+
create(context) {
13+
return {
14+
NewExpression(node) {
15+
if (
16+
node.callee.type === 'MemberExpression' &&
17+
node.callee.object.name === 'Promise' &&
18+
PROMISE_STATICS.indexOf(node.callee.property.name) > -1
19+
) {
20+
context.report({
21+
node,
22+
message: "Avoid calling 'new' on 'Promise.{{ name }}()'",
23+
data: { name: node.callee.property.name }
24+
})
25+
}
26+
}
27+
}
28+
}
29+
}

0 commit comments

Comments
 (0)