eslint-plugin-promise
Advanced tools
Comparing version 3.6.0 to 3.7.0
@@ -0,99 +1,112 @@ | ||
## 3.7.0 | ||
* Added `promise/valid-params` rule | ||
([#85](https://github.com/xjamundx/eslint-plugin-promise/pull/85)) | ||
* Added `promise/no-new-statics` rule | ||
([#82](https://github.com/xjamundx/eslint-plugin-promise/pull/82)) | ||
* Added fixer for `promise/param-names` rule | ||
([#99](https://github.com/xjamundx/eslint-plugin-promise/pull/99)) | ||
* Added rule documentation to each rule | ||
([#91](https://github.com/xjamundx/eslint-plugin-promise/pull/91)) | ||
## 3.6.0 | ||
- Added `['catch']` support in `catch-or-return` | ||
- Added `no-return-in-finally` rule | ||
- Fixed some formatting in the docs | ||
- Added `allowReject` option to `no-return-wrap` | ||
- Added exceptions for `no-callback-in-promise` | ||
* Added `['catch']` support in `catch-or-return` | ||
* Added `no-return-in-finally` rule | ||
* Fixed some formatting in the docs | ||
* Added `allowReject` option to `no-return-wrap` | ||
* Added exceptions for `no-callback-in-promise` | ||
## 3.5.0 | ||
- Addded support for recommended settings using `extends: plugin:promise/recommended` | ||
* Added support for recommended settings using | ||
`extends: plugin:promise/recommended` | ||
## 3.4.2 | ||
- Fixed always return false positive with ternary (#31) | ||
* Fixed always return false positive with ternary (#31) | ||
## 3.4.1 | ||
- fixed #49 | ||
* fixed #49 | ||
## 3.4.0 | ||
- new rule: avoid-new | ||
- new rule: no-promise-in-callback | ||
- new rule: no-callback-in-promise | ||
- new rule: no-nesting | ||
* new rule: avoid-new | ||
* new rule: no-promise-in-callback | ||
* new rule: no-callback-in-promise | ||
* new rule: no-nesting | ||
## 3.3.2 | ||
- Removed eslint from peerDeps | ||
* Removed eslint from peerDeps | ||
## 3.3.1 | ||
- Updated engines with proper stuff | ||
- Fixed bug for unreachable code | ||
* Updated engines with proper stuff | ||
* Fixed bug for unreachable code | ||
## 3.3.0 | ||
- Rule: `prefer-async-to-callbacks` added | ||
- Rule: `prefer-async-to-then` added | ||
* Rule: `prefer-async-to-callbacks` added | ||
* Rule: `prefer-async-to-then` added | ||
## 3.2.1 | ||
- Fix: `no-return-wrap` rule missing from index.js | ||
* Fix: `no-return-wrap` rule missing from index.js | ||
## 3.2.0 | ||
- Added `no-return-wrap` rule | ||
* Added `no-return-wrap` rule | ||
## 3.1.0 | ||
- Added multiple terminationMethods | ||
* Added multiple terminationMethods | ||
## 3.0.1 | ||
- Removed deprecated `always-catch` rule | ||
- FIX: always-return error with "fn && fn()" | ||
* Removed deprecated `always-catch` rule | ||
* FIX: always-return error with "fn && fn()" | ||
## 3.0.0 | ||
- Updated column and line numbers | ||
- Added flow analysis for better handling of if statements | ||
* Updated column and line numbers | ||
* Added flow analysis for better handling of if statements | ||
## 2.0.1 | ||
- Fixed type in docs | ||
* Fixed type in docs | ||
## 2.0.0 | ||
- ESLint 3.0 Support | ||
* ESLint 3.0 Support | ||
## 1.3.2 | ||
- Updated tests to run on eslint 2.0 | ||
- Fixed some issues with `no-native` rule | ||
* Updated tests to run on eslint 2.0 | ||
* Fixed some issues with `no-native` rule | ||
## 1.3.1 | ||
- Actually added `no-native` rule | ||
* Actually added `no-native` rule | ||
## 1.3.0 | ||
- Added `no-native` rule | ||
* Added `no-native` rule | ||
## 1.2.0 | ||
- Allow `throw` in `always-return` rule | ||
- Added `terminationMethod` option to `catch-or-return` rule | ||
* Allow `throw` in `always-return` rule | ||
* Added `terminationMethod` option to `catch-or-return` rule | ||
## 1.1.0 | ||
- Added `catch-or-return` rule | ||
* Added `catch-or-return` rule | ||
## 1.0.8 | ||
- Fixed crash issues | ||
* Fixed crash issues | ||
## 1.0.0 - 1.0.7 | ||
- Lots of basic feature updates and doc changes | ||
* Lots of basic feature updates and doc changes |
10
index.js
@@ -0,1 +1,3 @@ | ||
'use strict' | ||
module.exports = { | ||
@@ -14,3 +16,5 @@ rules: { | ||
'avoid-new': require('./rules/avoid-new'), | ||
'no-return-in-finally': require('./rules/no-return-in-finally') | ||
'no-new-statics': require('./rules/no-new-statics'), | ||
'no-return-in-finally': require('./rules/no-return-in-finally'), | ||
'valid-params': require('./rules/valid-params') | ||
}, | ||
@@ -36,3 +40,5 @@ rulesConfig: { | ||
'promise/avoid-new': 'warn', | ||
'promise/no-return-in-finally': 'warn' | ||
'promise/no-new-statics': 'error', | ||
'promise/no-return-in-finally': 'warn', | ||
'promise/valid-params': 'warn' | ||
} | ||
@@ -39,0 +45,0 @@ } |
{ | ||
"name": "eslint-plugin-promise", | ||
"version": "3.6.0", | ||
"version": "3.7.0", | ||
"description": "Enforce best practices for JavaScript promises", | ||
@@ -15,9 +15,23 @@ "keywords": [ | ||
"scripts": { | ||
"pretest": "standard", | ||
"test": "mocha test" | ||
"precommit": "lint-staged", | ||
"test": "jest", | ||
"lint": "eslint index.js rules __tests__ --ignore-pattern '**/*.json'" | ||
}, | ||
"devDependencies": { | ||
"eslint": "^3.0", | ||
"mocha": "^2.3.4", | ||
"standard": "^7.1.2" | ||
"doctoc": "^1.3.0", | ||
"eslint": "^4.17.0", | ||
"eslint-config-prettier": "^2.9.0", | ||
"eslint-config-standard": "^11.0.0-beta.0", | ||
"eslint-plugin-eslint-plugin": "^1.4.0", | ||
"eslint-plugin-import": "^2.8.0", | ||
"eslint-plugin-jest": "^21.12.2", | ||
"eslint-plugin-node": "^6.0.0", | ||
"eslint-plugin-prettier": "^2.6.0", | ||
"eslint-plugin-promise": "./", | ||
"eslint-plugin-standard": "^3.0.1", | ||
"husky": "^0.14.3", | ||
"jest": "^22.4.2", | ||
"jest-runner-eslint": "^0.4.0", | ||
"lint-staged": "^6.1.0", | ||
"prettier": "^1.10.2" | ||
}, | ||
@@ -27,3 +41,36 @@ "engines": { | ||
}, | ||
"license": "ISC" | ||
"license": "ISC", | ||
"lint-staged": { | ||
"concurrent": false, | ||
"linters": { | ||
"{README.md,CONTRIBUTING.md}": [ | ||
"doctoc --maxlevel 3 --notitle", | ||
"git add" | ||
], | ||
"*.js": ["prettier --write", "eslint --fix", "git add"], | ||
"*.+(json|md)": ["prettier --write", "git add"] | ||
} | ||
}, | ||
"prettier": { | ||
"semi": false, | ||
"singleQuote": true, | ||
"proseWrap": "always" | ||
}, | ||
"jest": { | ||
"projects": [ | ||
{ | ||
"displayName": "test", | ||
"testEnvironment": "node" | ||
}, | ||
{ | ||
"runner": "jest-runner-eslint", | ||
"displayName": "lint", | ||
"testMatch": [ | ||
"<rootDir>/rules/**/*.js", | ||
"<rootDir>/__tests__/**/*.js", | ||
"<rootDir>/index.js" | ||
] | ||
} | ||
] | ||
} | ||
} |
276
README.md
@@ -5,7 +5,19 @@ # eslint-plugin-promise | ||
[![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) | ||
[![travis-ci](https://travis-ci.org/xjamundx/eslint-plugin-promise.svg)](https://travis-ci.org/xjamundx/eslint-plugin-promise) | ||
[![travis-ci](https://travis-ci.org/xjamundx/eslint-plugin-promise.svg)](https://travis-ci.org/xjamundx/eslint-plugin-promise) | ||
[![npm version](https://badge.fury.io/js/eslint-plugin-promise.svg)](https://www.npmjs.com/package/eslint-plugin-promise) | ||
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com) | ||
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier) | ||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
* [Installation](#installation) | ||
* [Usage](#usage) | ||
* [Rules](#rules) | ||
* [Maintainers](#maintainers) | ||
* [License](#license) | ||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
## Installation | ||
@@ -16,3 +28,3 @@ | ||
``` | ||
$ npm i eslint --save-dev | ||
$ npm install eslint --save-dev | ||
``` | ||
@@ -26,17 +38,16 @@ | ||
**Note:** If you installed ESLint globally (using the `-g` flag) then you must also install `eslint-plugin-promise` globally. | ||
**Note:** If you installed ESLint globally (using the `-g` flag) then you must | ||
also install `eslint-plugin-promise` globally. | ||
## Usage | ||
Add `promise` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix: | ||
Add `promise` to the plugins section of your `.eslintrc` configuration file. You | ||
can omit the `eslint-plugin-` prefix: | ||
```json | ||
{ | ||
"plugins": [ | ||
"promise" | ||
] | ||
"plugins": ["promise"] | ||
} | ||
``` | ||
Then configure the rules you want to use under the rules section. | ||
@@ -46,14 +57,16 @@ | ||
{ | ||
"rules": { | ||
"promise/always-return": "error", | ||
"promise/no-return-wrap": "error", | ||
"promise/param-names": "error", | ||
"promise/catch-or-return": "error", | ||
"promise/no-native": "off", | ||
"promise/no-nesting": "warn", | ||
"promise/no-promise-in-callback": "warn", | ||
"promise/no-callback-in-promise": "warn", | ||
"promise/avoid-new": "warn", | ||
"promise/no-return-in-finally": "warn" | ||
} | ||
"rules": { | ||
"promise/always-return": "error", | ||
"promise/no-return-wrap": "error", | ||
"promise/param-names": "error", | ||
"promise/catch-or-return": "error", | ||
"promise/no-native": "off", | ||
"promise/no-nesting": "warn", | ||
"promise/no-promise-in-callback": "warn", | ||
"promise/no-callback-in-promise": "warn", | ||
"promise/avoid-new": "warn", | ||
"promise/no-new-statics": "error", | ||
"promise/no-return-in-finally": "warn", | ||
"promise/valid-params": "warn" | ||
} | ||
} | ||
@@ -66,5 +79,3 @@ ``` | ||
{ | ||
"extends": [ | ||
"plugin:promise/recommended" | ||
] | ||
"extends": ["plugin:promise/recommended"] | ||
} | ||
@@ -75,19 +86,19 @@ ``` | ||
### Promise Rules | ||
| rule | description | recommended | fixable | | ||
| -------------------------------------------------------- | -------------------------------------------------------------------------------- | ----------- | -------- | | ||
| [`catch-or-return`][catch-or-return] | Enforces the use of `catch()` on un-returned promises. | :bangbang: | | | ||
| [`no-return-wrap`][no-return-wrap] | Avoid wrapping values in `Promise.resolve` or `Promise.reject` when not needed. | :bangbang: | | | ||
| [`param-names`][param-names] | Enforce consistent param names when creating new promises. | :bangbang: | :wrench: | | ||
| [`always-return`][always-return] | Return inside each `then()` to create readable and reusable Promise chains. | :bangbang: | | | ||
| [`no-native`][no-native] | In an ES5 environment, make sure to create a `Promise` constructor before using. | | | | ||
| [`no-nesting`][no-nesting] | Avoid nested `then()` or `catch()` statements | :warning: | | | ||
| [`no-promise-in-callback`][no-promise-in-callback] | Avoid using promises inside of callbacks | :warning: | | | ||
| [`no-callback-in-promise`][no-callback-in-promise] | Avoid calling `cb()` inside of a `then()` (use [nodeify][] instead) | :warning: | | | ||
| [`avoid-new` ][avoid-new] | Avoid creating `new` promises outside of utility libs (use [pify][] instead) | :warning: | | | ||
| [`no-new-statics`][no-new-statics] | Avoid calling `new` on a Promise static method | :bangbang: | | | ||
| [`no-return-in-finally`][no-return-in-finally] | Disallow return statements in `finally()` | :warning: | | | ||
| [`valid-params`][valid-params] | Ensures the proper number of arguments are passed to Promise functions | :warning: | | | ||
| [`prefer-await-to-then`][prefer-await-to-then] | Prefer `await` to `then()` for reading Promise values | :seven: | | | ||
| [`prefer-await-to-callbacks`][prefer-await-to-callbacks] | Prefer async/await to the callback pattern | :seven: | | | ||
| recommended | rule | description | | ||
| ----------- | --------------------------- | -------------------------------------------------------------------------------- | | ||
| :bangbang: | `catch-or-return` | Enforces the use of `catch()` on un-returned promises. | | ||
| :bangbang: | `no-return-wrap` | Avoid wrapping values in `Promise.resolve` or `Promise.reject` when not needed. | | ||
| :bangbang: | `param-names` | Enforce consistent param names when creating new promises. | | ||
| :bangbang: | `always-return` | Return inside each `then()` to create readable and reusable Promise chains. | | ||
| | `no-native` | In an ES5 environment, make sure to create a `Promise` constructor before using. | | ||
| :warning: | `no-nesting` | Avoid nested `then()` or `catch()` statements | | ||
| :warning: | `no-promise-in-callback` | Avoid using promises inside of callbacks | | ||
| :warning: | `no-callback-in-promise` | Avoid calling `cb()` inside of a `then()` (use [nodeify][] instead) | | ||
| :warning: | `avoid-new` | Avoid creating `new` promises outside of utility libs (use [pify][] instead) | | ||
| :warning: | `no-return-in-finally` | Disallow return statements in `finally()` | | ||
| :seven: | `prefer-await-to-then` | Prefer `await` to `then()` for reading Promise values | | ||
| :seven: | `prefer-await-to-callbacks` | Prefer async/await to the callback pattern | | ||
**Key** | ||
@@ -100,166 +111,31 @@ | ||
| :seven: | ES2017 Async Await rules | | ||
| :wrench: | Rule is fixable with `eslint --fix` | | ||
[nodeify]: https://www.npmjs.com/package/nodeify | ||
[pify]: https://www.npmjs.com/package/pify | ||
## Maintainers | ||
### Rule: `catch-or-return` | ||
* Jamund Ferguson - [@xjamundx][] | ||
* Macklin Underdown - [@macklinu][] | ||
Ensure that each time a `then()` is applied to a promise, a | ||
`catch()` is applied as well. Exceptions are made if you are | ||
returning that promise. | ||
## License | ||
#### Valid | ||
* (c) MMXV jden <mailto:jason@denizac.org> - ISC license. | ||
* (c) 2016 Jamund Ferguson <mailto:jamund@gmail.com> - ISC license. | ||
```js | ||
myPromise.then(doSomething).catch(errors); | ||
myPromise.then(doSomething).then(doSomethingElse).catch(errors); | ||
function doSomethingElse() { return myPromise.then(doSomething) } | ||
``` | ||
#### Invalid | ||
```js | ||
myPromise.then(doSomething); | ||
myPromise.then(doSomething, catchErrors); // catch() may be a little better | ||
function doSomethingElse() { myPromise.then(doSomething) } | ||
``` | ||
#### Options | ||
#### `allowThen` | ||
You can pass an `{ allowThen: true }` as an option to this rule | ||
to allow for `.then(null, fn)` to be used instead of `catch()` at | ||
the end of the promise chain. | ||
#### `terminationMethod` | ||
You can pass a `{ terminationMethod: 'done' }` as an option to this rule | ||
to require `done()` instead of `catch()` at the end of the promise chain. | ||
This is useful for many non-standard Promise implementations. | ||
You can also pass an array of methods such as | ||
`{ terminationMethod: ['catch', 'asCallback', 'finally'] }`. | ||
This will allow any of | ||
```js | ||
Promise.resolve(1).then(() => { throw new Error('oops') }).catch(logerror) | ||
Promise.resolve(1).then(() => { throw new Error('oops') }).asCallback(cb) | ||
Promise.resolve(1).then(() => { throw new Error('oops') }).finally(cleanUp) | ||
``` | ||
### Rule: `always-return` | ||
Ensure that inside a `then()` you make sure to `return` a new promise or value. | ||
See http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html (rule #5) | ||
for more info on why that's a good idea. | ||
We also allow someone to `throw` inside a `then()` which is essentially the same as `return Promise.reject()`. | ||
#### Valid | ||
```js | ||
myPromise.then((val) => val * 2)); | ||
myPromise.then(function(val) { return val * 2; }); | ||
myPromise.then(doSomething); // could be either | ||
myPromise.then((b) => { if (b) { return "yes" } else { return "no" } }); | ||
``` | ||
#### Invalid | ||
```js | ||
myPromise.then(function(val) {}); | ||
myPromise.then(() => { doSomething(); }); | ||
myPromise.then((b) => { if (b) { return "yes" } else { forgotToReturn(); } }); | ||
``` | ||
### `param-names` | ||
Enforce standard parameter names for Promise constructors | ||
#### Valid | ||
```js | ||
new Promise(function (resolve) { ... }) | ||
new Promise(function (resolve, reject) { ... }) | ||
``` | ||
#### Invalid | ||
```js | ||
new Promise(function (reject, resolve) { ... }) // incorrect order | ||
new Promise(function (ok, fail) { ... }) // non-standard parameter names | ||
``` | ||
Ensures that `new Promise()` is instantiated with the parameter names `resolve, reject` to avoid confusion with order such as `reject, resolve`. The Promise constructor uses the [RevealingConstructor pattern](https://blog.domenic.me/the-revealing-constructor-pattern/). Using the same parameter names as the language specification makes code more uniform and easier to understand. | ||
### `no-native` | ||
Ensure that `Promise` is included fresh in each file instead of relying | ||
on the existence of a native promise implementation. Helpful if you want | ||
to use `bluebird` or if you don't intend to use an ES6 Promise shim. | ||
#### Valid | ||
```js | ||
var Promise = require("bluebird"); | ||
var x = Promise.resolve("good"); | ||
``` | ||
#### Invalid | ||
```js | ||
var x = Promise.resolve("bad"); | ||
``` | ||
### Rule: `no-return-wrap` | ||
Ensure that inside a `then()` or a `catch()` we always `return` | ||
or `throw` a raw value instead of wrapping in `Promise.resolve` | ||
or `Promise.reject` | ||
#### Valid | ||
```js | ||
myPromise.then(function(val) { | ||
return val * 2; | ||
}); | ||
myPromise.then(function(val) { | ||
throw "bad thing"; | ||
}); | ||
``` | ||
#### Invalid | ||
```js | ||
myPromise.then(function(val) { | ||
return Promise.resolve(val * 2); | ||
}); | ||
myPromise.then(function(val) { | ||
return Promise.reject("bad thing"); | ||
}) | ||
``` | ||
#### Options | ||
#### `allowReject` | ||
Pass `{ allowReject: true }` as an option to this rule to permit wrapping returned values with `Promise.reject`, such as when you would use it as another way to reject the promise. | ||
### Rule: `no-return-in-finally` | ||
Disallow return statements inside a callback passed to `finally()`, since nothing would consume what's returned. | ||
#### Valid | ||
```js | ||
myPromise.finally(function(val) { | ||
console.log('value:', val); | ||
}); | ||
``` | ||
#### Invalid | ||
```js | ||
myPromise.finally(function(val) { | ||
return val; | ||
}) | ||
``` | ||
## Etc | ||
- (c) MMXV jden <jason@denizac.org> - ISC license. | ||
- (c) 2016 Jamund Ferguson <jamund@gmail.com> - ISC license. | ||
[catch-or-return]: docs/rules/catch-or-return.md | ||
[no-return-wrap]: docs/rules/no-return-wrap.md | ||
[param-names]: docs/rules/param-names.md | ||
[always-return]: docs/rules/always-return.md | ||
[no-native]: docs/rules/no-native.md | ||
[no-nesting]: docs/rules/no-nesting.md | ||
[no-promise-in-callback]: docs/rules/no-promise-in-callback.md | ||
[no-callback-in-promise]: docs/rules/no-callback-in-promise.md | ||
[avoid-new]: docs/rules/avoid-new.md | ||
[no-new-statics]: docs/rules/no-new-statics.md | ||
[no-return-in-finally]: docs/rules/no-return-in-finally.md | ||
[valid-params]: docs/rules/valid-params.md | ||
[prefer-await-to-then]: docs/rules/prefer-await-to-then.md | ||
[prefer-await-to-callbacks]: docs/rules/prefer-await-to-callbacks.md | ||
[nodeify]: https://www.npmjs.com/package/nodeify | ||
[pify]: https://www.npmjs.com/package/pify | ||
[@macklinu]: https://github.com/macklinu | ||
[@xjamundx]: https://github.com/xjamundx |
@@ -1,2 +0,6 @@ | ||
function isFunctionWithBlockStatement (node) { | ||
'use strict' | ||
const getDocsUrl = require('./lib/get-docs-url') | ||
function isFunctionWithBlockStatement(node) { | ||
if (node.type === 'FunctionExpression') { | ||
@@ -11,27 +15,25 @@ return true | ||
function isThenCallExpression (node) { | ||
function isThenCallExpression(node) { | ||
return ( | ||
node.type === 'CallExpression' && | ||
node.callee.type === 'MemberExpression' && | ||
node.callee.property.name === 'then' | ||
node.type === 'CallExpression' && | ||
node.callee.type === 'MemberExpression' && | ||
node.callee.property.name === 'then' | ||
) | ||
} | ||
function isFirstArgument (node) { | ||
function isFirstArgument(node) { | ||
return ( | ||
node.parent && | ||
node.parent.arguments && | ||
node.parent.arguments[0] === node | ||
node.parent && node.parent.arguments && node.parent.arguments[0] === node | ||
) | ||
} | ||
function isInlineThenFunctionExpression (node) { | ||
function isInlineThenFunctionExpression(node) { | ||
return ( | ||
isFunctionWithBlockStatement(node) && | ||
isThenCallExpression(node.parent) && | ||
isFirstArgument(node) | ||
isFunctionWithBlockStatement(node) && | ||
isThenCallExpression(node.parent) && | ||
isFirstArgument(node) | ||
) | ||
} | ||
function hasParentReturnStatement (node) { | ||
function hasParentReturnStatement(node) { | ||
if (node && node.parent && node.parent.type) { | ||
@@ -52,3 +54,3 @@ // if the parent is a then, and we haven't returned anything, fail | ||
function peek (arr) { | ||
function peek(arr) { | ||
return arr[arr.length - 1] | ||
@@ -58,3 +60,8 @@ } | ||
module.exports = { | ||
create: function (context) { | ||
meta: { | ||
docs: { | ||
url: getDocsUrl('always-return') | ||
} | ||
}, | ||
create: function(context) { | ||
// funcInfoStack is a stack representing the stack of currently executing | ||
@@ -89,7 +96,7 @@ // functions | ||
// loc: <loc> } } } ] | ||
var funcInfoStack = [] | ||
const funcInfoStack = [] | ||
function markCurrentBranchAsGood () { | ||
var funcInfo = peek(funcInfoStack) | ||
var currentBranchID = peek(funcInfo.branchIDStack) | ||
function markCurrentBranchAsGood() { | ||
const funcInfo = peek(funcInfoStack) | ||
const currentBranchID = peek(funcInfo.branchIDStack) | ||
if (funcInfo.branchInfoMap[currentBranchID]) { | ||
@@ -105,14 +112,14 @@ funcInfo.branchInfoMap[currentBranchID].good = true | ||
onCodePathSegmentStart: function (segment, node) { | ||
var funcInfo = peek(funcInfoStack) | ||
onCodePathSegmentStart: function(segment, node) { | ||
const funcInfo = peek(funcInfoStack) | ||
funcInfo.branchIDStack.push(segment.id) | ||
funcInfo.branchInfoMap[segment.id] = {good: false, node: node} | ||
funcInfo.branchInfoMap[segment.id] = { good: false, node: node } | ||
}, | ||
onCodePathSegmentEnd: function (segment, node) { | ||
var funcInfo = peek(funcInfoStack) | ||
onCodePathSegmentEnd: function(segment, node) { | ||
const funcInfo = peek(funcInfoStack) | ||
funcInfo.branchIDStack.pop() | ||
}, | ||
onCodePathStart: function (path, node) { | ||
onCodePathStart: function(path, node) { | ||
funcInfoStack.push({ | ||
@@ -124,4 +131,4 @@ branchIDStack: [], | ||
onCodePathEnd: function (path, node) { | ||
var funcInfo = funcInfoStack.pop() | ||
onCodePathEnd: function(path, node) { | ||
const funcInfo = funcInfoStack.pop() | ||
@@ -132,5 +139,5 @@ if (!isInlineThenFunctionExpression(node)) { | ||
path.finalSegments.forEach((segment) => { | ||
var id = segment.id | ||
var branch = funcInfo.branchInfoMap[id] | ||
path.finalSegments.forEach(segment => { | ||
const id = segment.id | ||
const branch = funcInfo.branchInfoMap[id] | ||
if (!branch.good) { | ||
@@ -142,5 +149,5 @@ if (hasParentReturnStatement(branch.node)) { | ||
// check shortcircuit syntax like `x && x()` and `y || x()`` | ||
var prevSegments = segment.prevSegments | ||
for (var ii = prevSegments.length - 1; ii >= 0; --ii) { | ||
var prevSegment = prevSegments[ii] | ||
const prevSegments = segment.prevSegments | ||
for (let ii = prevSegments.length - 1; ii >= 0; --ii) { | ||
const prevSegment = prevSegments[ii] | ||
if (funcInfo.branchInfoMap[prevSegment.id].good) return | ||
@@ -147,0 +154,0 @@ } |
@@ -6,7 +6,18 @@ /** | ||
module.exports = function (context) { | ||
return { | ||
NewExpression: function (node) { | ||
if (node.callee.name === 'Promise') { | ||
context.report(node, 'Avoid creating new promises.') | ||
'use strict' | ||
const getDocsUrl = require('./lib/get-docs-url') | ||
module.exports = { | ||
meta: { | ||
docs: { | ||
url: getDocsUrl('avoid-new') | ||
} | ||
}, | ||
create: function(context) { | ||
return { | ||
NewExpression: function(node) { | ||
if (node.callee.name === 'Promise') { | ||
context.report({ node, message: 'Avoid creating new promises.' }) | ||
} | ||
} | ||
@@ -13,0 +24,0 @@ } |
@@ -7,9 +7,17 @@ /** | ||
var isPromise = require('./lib/is-promise') | ||
'use strict' | ||
const getDocsUrl = require('./lib/get-docs-url') | ||
const isPromise = require('./lib/is-promise') | ||
module.exports = { | ||
create: function (context) { | ||
var options = context.options[0] || {} | ||
var allowThen = options.allowThen | ||
var terminationMethod = options.terminationMethod || 'catch' | ||
meta: { | ||
docs: { | ||
url: getDocsUrl('catch-or-return') | ||
} | ||
}, | ||
create: function(context) { | ||
const options = context.options[0] || {} | ||
const allowThen = options.allowThen | ||
let terminationMethod = options.terminationMethod || 'catch' | ||
@@ -21,3 +29,3 @@ if (typeof terminationMethod === 'string') { | ||
return { | ||
ExpressionStatement: function (node) { | ||
ExpressionStatement: function(node) { | ||
if (!isPromise(node.expression)) { | ||
@@ -28,3 +36,4 @@ return | ||
// somePromise.then(a, b) | ||
if (allowThen && | ||
if ( | ||
allowThen && | ||
node.expression.type === 'CallExpression' && | ||
@@ -39,3 +48,4 @@ node.expression.callee.type === 'MemberExpression' && | ||
// somePromise.catch() | ||
if (node.expression.type === 'CallExpression' && | ||
if ( | ||
node.expression.type === 'CallExpression' && | ||
node.expression.callee.type === 'MemberExpression' && | ||
@@ -48,3 +58,4 @@ terminationMethod.indexOf(node.expression.callee.property.name) !== -1 | ||
// somePromise['catch']() | ||
if (node.expression.type === 'CallExpression' && | ||
if ( | ||
node.expression.type === 'CallExpression' && | ||
node.expression.callee.type === 'MemberExpression' && | ||
@@ -57,3 +68,7 @@ node.expression.callee.property.type === 'Literal' && | ||
context.report(node, 'Expected ' + terminationMethod + '() or return') | ||
context.report({ | ||
node, | ||
message: 'Expected {{ terminationMethod }}() or return', | ||
data: { terminationMethod } | ||
}) | ||
} | ||
@@ -60,0 +75,0 @@ } |
@@ -7,6 +7,8 @@ /** | ||
function hasPromiseCallback (node) { | ||
'use strict' | ||
function hasPromiseCallback(node) { | ||
if (node.type !== 'CallExpression') return | ||
if (node.callee.type !== 'MemberExpression') return | ||
var propertyName = node.callee.property.name | ||
const propertyName = node.callee.property.name | ||
return propertyName === 'then' || propertyName === 'catch' | ||
@@ -13,0 +15,0 @@ } |
@@ -1,8 +0,10 @@ | ||
var isNamedCallback = require('./is-named-callback') | ||
'use strict' | ||
function isCallingBack (node, exceptions) { | ||
var isCallExpression = node.type === 'CallExpression' | ||
var callee = node.callee || {} | ||
var nameIsCallback = isNamedCallback(callee.name, exceptions) | ||
var isCB = isCallExpression && nameIsCallback | ||
const isNamedCallback = require('./is-named-callback') | ||
function isCallingBack(node, exceptions) { | ||
const isCallExpression = node.type === 'CallExpression' | ||
const callee = node.callee || {} | ||
const nameIsCallback = isNamedCallback(callee.name, exceptions) | ||
const isCB = isCallExpression && nameIsCallback | ||
return isCB | ||
@@ -9,0 +11,0 @@ } |
@@ -1,5 +0,8 @@ | ||
var isInsidePromise = require('./is-inside-promise') | ||
'use strict' | ||
function isInsideCallback (node) { | ||
var isCallExpression = node.type === 'FunctionExpression' || | ||
const isInsidePromise = require('./is-inside-promise') | ||
function isInsideCallback(node) { | ||
const isCallExpression = | ||
node.type === 'FunctionExpression' || | ||
node.type === 'ArrowFunctionExpression' || | ||
@@ -11,5 +14,5 @@ node.type === 'FunctionDeclaration' // this may be controversial | ||
var name = node.params && node.params[0] && node.params[0].name | ||
var firstArgIsError = name === 'err' || name === 'error' | ||
var isInACallback = isCallExpression && firstArgIsError | ||
const name = node.params && node.params[0] && node.params[0].name | ||
const firstArgIsError = name === 'err' || name === 'error' | ||
const isInACallback = isCallExpression && firstArgIsError | ||
return isInACallback | ||
@@ -16,0 +19,0 @@ } |
@@ -1,9 +0,12 @@ | ||
function isInsidePromise (node) { | ||
var isFunctionExpression = node.type === 'FunctionExpression' || | ||
node.type === 'ArrowFunctionExpression' | ||
var parent = node.parent || {} | ||
var callee = parent.callee || {} | ||
var name = callee.property && callee.property.name || '' | ||
var parentIsPromise = name === 'then' || name === 'catch' | ||
var isInCB = isFunctionExpression && parentIsPromise | ||
'use strict' | ||
function isInsidePromise(node) { | ||
const isFunctionExpression = | ||
node.type === 'FunctionExpression' || | ||
node.type === 'ArrowFunctionExpression' | ||
const parent = node.parent || {} | ||
const callee = parent.callee || {} | ||
const name = (callee.property && callee.property.name) || '' | ||
const parentIsPromise = name === 'then' || name === 'catch' | ||
const isInCB = isFunctionExpression && parentIsPromise | ||
return isInCB | ||
@@ -10,0 +13,0 @@ } |
@@ -1,10 +0,14 @@ | ||
var callbacks = ['done', 'cb', 'callback', 'next'] | ||
'use strict' | ||
module.exports = function isNamedCallback (potentialCallbackName, exceptions) { | ||
for (var i = 0; i < exceptions.length; i++) { | ||
callbacks = callbacks.filter(function (item) { return item !== exceptions[i] }) | ||
let callbacks = ['done', 'cb', 'callback', 'next'] | ||
module.exports = function isNamedCallback(potentialCallbackName, exceptions) { | ||
for (let i = 0; i < exceptions.length; i++) { | ||
callbacks = callbacks.filter(function(item) { | ||
return item !== exceptions[i] | ||
}) | ||
} | ||
return callbacks.some(function (trueCallbackName) { | ||
return callbacks.some(function(trueCallbackName) { | ||
return potentialCallbackName === trueCallbackName | ||
}) | ||
} |
@@ -5,32 +5,30 @@ /** | ||
*/ | ||
var STATIC_METHODS = [ | ||
'all', | ||
'race', | ||
'reject', | ||
'resolve' | ||
] | ||
'use strict' | ||
function isPromise (expression) { | ||
return ( // hello.then() | ||
expression.type === 'CallExpression' && | ||
expression.callee.type === 'MemberExpression' && | ||
expression.callee.property.name === 'then' | ||
) || ( // hello.catch() | ||
expression.type === 'CallExpression' && | ||
expression.callee.type === 'MemberExpression' && | ||
expression.callee.property.name === 'catch' | ||
) || ( // hello.finally() | ||
expression.type === 'CallExpression' && | ||
expression.callee.type === 'MemberExpression' && | ||
expression.callee.property.name === 'finally' | ||
) || ( // somePromise.ANYTHING() | ||
expression.type === 'CallExpression' && | ||
expression.callee.type === 'MemberExpression' && | ||
isPromise(expression.callee.object) | ||
) || ( // Promise.STATIC_METHOD() | ||
expression.type === 'CallExpression' && | ||
expression.callee.type === 'MemberExpression' && | ||
expression.callee.object.type === 'Identifier' && | ||
expression.callee.object.name === 'Promise' && | ||
STATIC_METHODS.indexOf(expression.callee.property.name) !== -1 | ||
const PROMISE_STATICS = require('./promise-statics') | ||
function isPromise(expression) { | ||
return ( | ||
// hello.then() | ||
(expression.type === 'CallExpression' && | ||
expression.callee.type === 'MemberExpression' && | ||
expression.callee.property.name === 'then') || | ||
// hello.catch() | ||
(expression.type === 'CallExpression' && | ||
expression.callee.type === 'MemberExpression' && | ||
expression.callee.property.name === 'catch') || | ||
// hello.finally() | ||
(expression.type === 'CallExpression' && | ||
expression.callee.type === 'MemberExpression' && | ||
expression.callee.property.name === 'finally') || | ||
// somePromise.ANYTHING() | ||
(expression.type === 'CallExpression' && | ||
expression.callee.type === 'MemberExpression' && | ||
isPromise(expression.callee.object)) || | ||
// Promise.STATIC_METHOD() | ||
(expression.type === 'CallExpression' && | ||
expression.callee.type === 'MemberExpression' && | ||
expression.callee.object.type === 'Identifier' && | ||
expression.callee.object.name === 'Promise' && | ||
PROMISE_STATICS.indexOf(expression.callee.property.name) !== -1) | ||
) | ||
@@ -37,0 +35,0 @@ } |
@@ -6,27 +6,49 @@ /** | ||
var hasPromiseCallback = require('./lib/has-promise-callback') | ||
var isInsidePromise = require('./lib/is-inside-promise') | ||
var isCallback = require('./lib/is-callback') | ||
'use strict' | ||
module.exports = function (context) { | ||
return { | ||
CallExpression: function (node) { | ||
var options = context.options[0] || {} | ||
var exceptions = options.exceptions || [] | ||
if (!isCallback(node, exceptions)) { | ||
// in general we send you packing if you're not a callback | ||
// but we also need to watch out for whatever.then(cb) | ||
if (hasPromiseCallback(node)) { | ||
var name = node.arguments && node.arguments[0] && node.arguments[0].name | ||
if (name === 'callback' || name === 'cb' || name === 'next' || name === 'done') { | ||
context.report(node.arguments[0], 'Avoid calling back inside of a promise.') | ||
const getDocsUrl = require('./lib/get-docs-url') | ||
const hasPromiseCallback = require('./lib/has-promise-callback') | ||
const isInsidePromise = require('./lib/is-inside-promise') | ||
const isCallback = require('./lib/is-callback') | ||
module.exports = { | ||
meta: { | ||
docs: { | ||
url: getDocsUrl('no-callback-in-promise') | ||
} | ||
}, | ||
create: function(context) { | ||
return { | ||
CallExpression: function(node) { | ||
const options = context.options[0] || {} | ||
const exceptions = options.exceptions || [] | ||
if (!isCallback(node, exceptions)) { | ||
// in general we send you packing if you're not a callback | ||
// but we also need to watch out for whatever.then(cb) | ||
if (hasPromiseCallback(node)) { | ||
const name = | ||
node.arguments && node.arguments[0] && node.arguments[0].name | ||
if ( | ||
name === 'callback' || | ||
name === 'cb' || | ||
name === 'next' || | ||
name === 'done' | ||
) { | ||
context.report({ | ||
node: node.arguments[0], | ||
message: 'Avoid calling back inside of a promise.' | ||
}) | ||
} | ||
} | ||
return | ||
} | ||
return | ||
if (context.getAncestors().some(isInsidePromise)) { | ||
context.report({ | ||
node, | ||
message: 'Avoid calling back inside of a promise.' | ||
}) | ||
} | ||
} | ||
if (context.getAncestors().some(isInsidePromise)) { | ||
context.report(node, 'Avoid calling back inside of a promise.') | ||
} | ||
} | ||
} | ||
} |
@@ -6,4 +6,6 @@ // Borrowed from here: | ||
function isDeclared (scope, ref) { | ||
return scope.variables.some(function (variable) { | ||
const getDocsUrl = require('./lib/get-docs-url') | ||
function isDeclared(scope, ref) { | ||
return scope.variables.some(function(variable) { | ||
if (variable.name !== ref.identifier.name) { | ||
@@ -22,4 +24,9 @@ return false | ||
module.exports = { | ||
create: function (context) { | ||
var MESSAGE = '"{{name}}" is not defined.' | ||
meta: { | ||
docs: { | ||
url: getDocsUrl('no-native') | ||
} | ||
}, | ||
create: function(context) { | ||
const MESSAGE = '"{{name}}" is not defined.' | ||
@@ -34,6 +41,6 @@ /** | ||
return { | ||
'Program:exit': function () { | ||
var scope = context.getScope() | ||
'Program:exit': function() { | ||
const scope = context.getScope() | ||
scope.implicit.left.forEach(function (ref) { | ||
scope.implicit.left.forEach(function(ref) { | ||
if (ref.identifier.name !== 'Promise') { | ||
@@ -44,3 +51,7 @@ return | ||
if (!isDeclared(scope, ref)) { | ||
context.report(ref.identifier, MESSAGE, { name: ref.identifier.name }) | ||
context.report({ | ||
node: ref.identifier, | ||
message: MESSAGE, | ||
data: { name: ref.identifier.name } | ||
}) | ||
} | ||
@@ -47,0 +58,0 @@ }) |
@@ -6,11 +6,21 @@ /** | ||
var hasPromiseCallback = require('./lib/has-promise-callback') | ||
var isInsidePromise = require('./lib/is-inside-promise') | ||
'use strict' | ||
module.exports = function (context) { | ||
return { | ||
CallExpression: function (node) { | ||
if (!hasPromiseCallback(node)) return | ||
if (context.getAncestors().some(isInsidePromise)) { | ||
context.report(node, 'Avoid nesting promises.') | ||
const getDocsUrl = require('./lib/get-docs-url') | ||
const hasPromiseCallback = require('./lib/has-promise-callback') | ||
const isInsidePromise = require('./lib/is-inside-promise') | ||
module.exports = { | ||
meta: { | ||
docs: { | ||
url: getDocsUrl('no-nesting') | ||
} | ||
}, | ||
create: function(context) { | ||
return { | ||
CallExpression: function(node) { | ||
if (!hasPromiseCallback(node)) return | ||
if (context.getAncestors().some(isInsidePromise)) { | ||
context.report({ node, message: 'Avoid nesting promises.' }) | ||
} | ||
} | ||
@@ -17,0 +27,0 @@ } |
@@ -6,19 +6,32 @@ /** | ||
var isPromise = require('./lib/is-promise') | ||
var isInsideCallback = require('./lib/is-inside-callback') | ||
'use strict' | ||
module.exports = function (context) { | ||
return { | ||
CallExpression: function (node) { | ||
if (!isPromise(node)) return | ||
const getDocsUrl = require('./lib/get-docs-url') | ||
const isPromise = require('./lib/is-promise') | ||
const isInsideCallback = require('./lib/is-inside-callback') | ||
// if i'm returning the promise, it's probably not really a callback | ||
// function, and I should be okay.... | ||
if (node.parent.type === 'ReturnStatement') return | ||
module.exports = { | ||
meta: { | ||
docs: { | ||
url: getDocsUrl('no-promise-in-callback') | ||
} | ||
}, | ||
create: function(context) { | ||
return { | ||
CallExpression: function(node) { | ||
if (!isPromise(node)) return | ||
// what about if the parent is an ArrowFunctionExpression | ||
// would that imply an implicit return? | ||
// if i'm returning the promise, it's probably not really a callback | ||
// function, and I should be okay.... | ||
if (node.parent.type === 'ReturnStatement') return | ||
if (context.getAncestors().some(isInsideCallback)) { | ||
context.report(node.callee, 'Avoid using promises inside of callbacks.') | ||
// what about if the parent is an ArrowFunctionExpression | ||
// would that imply an implicit return? | ||
if (context.getAncestors().some(isInsideCallback)) { | ||
context.report({ | ||
node: node.callee, | ||
message: 'Avoid using promises inside of callbacks.' | ||
}) | ||
} | ||
} | ||
@@ -25,0 +38,0 @@ } |
@@ -1,12 +0,36 @@ | ||
var isPromise = require('./lib/is-promise') | ||
'use strict' | ||
const getDocsUrl = require('./lib/get-docs-url') | ||
const isPromise = require('./lib/is-promise') | ||
module.exports = { | ||
create: function (context) { | ||
meta: { | ||
docs: { | ||
url: getDocsUrl('no-return-in-finally') | ||
} | ||
}, | ||
create: function(context) { | ||
return { | ||
CallExpression: function (node) { | ||
CallExpression: function(node) { | ||
if (isPromise(node)) { | ||
if (node.callee && node.callee.property && node.callee.property.name === 'finally') { | ||
if (node.arguments && node.arguments[0] && node.arguments[0].body && node.arguments[0].body.body) { | ||
if (node.arguments[0].body.body.some(function (statement) { return statement.type === 'ReturnStatement' })) { | ||
context.report(node.callee.property, 'No return in finally') | ||
if ( | ||
node.callee && | ||
node.callee.property && | ||
node.callee.property.name === 'finally' | ||
) { | ||
if ( | ||
node.arguments && | ||
node.arguments[0] && | ||
node.arguments[0].body && | ||
node.arguments[0].body.body | ||
) { | ||
if ( | ||
node.arguments[0].body.body.some(function(statement) { | ||
return statement.type === 'ReturnStatement' | ||
}) | ||
) { | ||
context.report({ | ||
node: node.callee.property, | ||
message: 'No return in finally' | ||
}) | ||
} | ||
@@ -13,0 +37,0 @@ } |
@@ -9,8 +9,9 @@ /** | ||
var isPromise = require('./lib/is-promise') | ||
var rejectMessage = 'Expected throw instead of Promise.reject' | ||
var resolveMessage = 'Avoid wrapping return values in Promise.resolve' | ||
const getDocsUrl = require('./lib/get-docs-url') | ||
const isPromise = require('./lib/is-promise') | ||
const rejectMessage = 'Expected throw instead of Promise.reject' | ||
const resolveMessage = 'Avoid wrapping return values in Promise.resolve' | ||
function isInPromise (context) { | ||
var expression = context.getAncestors().filter(function (node) { | ||
function isInPromise(context) { | ||
const expression = context.getAncestors().filter(function(node) { | ||
return node.type === 'ExpressionStatement' | ||
@@ -22,8 +23,13 @@ })[0] | ||
module.exports = { | ||
create: function (context) { | ||
var options = context.options[0] || {} | ||
var allowReject = options.allowReject | ||
meta: { | ||
docs: { | ||
url: getDocsUrl('no-return-wrap') | ||
} | ||
}, | ||
create: function(context) { | ||
const options = context.options[0] || {} | ||
const allowReject = options.allowReject | ||
return { | ||
ReturnStatement: function (node) { | ||
ReturnStatement: function(node) { | ||
if (isInPromise(context)) { | ||
@@ -35,5 +41,8 @@ if (node.argument) { | ||
if (node.argument.callee.property.name === 'resolve') { | ||
context.report(node, resolveMessage) | ||
} else if (!allowReject && node.argument.callee.property.name === 'reject') { | ||
context.report(node, rejectMessage) | ||
context.report({ node, message: resolveMessage }) | ||
} else if ( | ||
!allowReject && | ||
node.argument.callee.property.name === 'reject' | ||
) { | ||
context.report({ node, message: rejectMessage }) | ||
} | ||
@@ -40,0 +49,0 @@ } |
@@ -0,16 +1,37 @@ | ||
'use strict' | ||
const getDocsUrl = require('./lib/get-docs-url') | ||
module.exports = { | ||
create: function (context) { | ||
meta: { | ||
docs: { | ||
url: getDocsUrl('param-names') | ||
}, | ||
fixable: 'code' | ||
}, | ||
create(context) { | ||
return { | ||
NewExpression: function (node) { | ||
NewExpression(node) { | ||
if (node.callee.name === 'Promise' && node.arguments.length === 1) { | ||
var params = node.arguments[0].params | ||
const params = node.arguments[0].params | ||
if (!params || !params.length) { return } | ||
if (params[0].name !== 'resolve') { | ||
return context.report(node, 'Promise constructor parameters must be named resolve, reject') | ||
if (!params || !params.length) { | ||
return | ||
} | ||
if (params[1] && params[1].name !== 'reject') { | ||
return context.report(node, 'Promise constructor parameters must be named resolve, reject') | ||
if ( | ||
params[0].name !== 'resolve' || | ||
(params[1] && params[1].name !== 'reject') | ||
) { | ||
context.report({ | ||
node, | ||
message: | ||
'Promise constructor parameters must be named resolve, reject', | ||
fix(fixer) { | ||
return [ | ||
fixer.replaceText(params[0], 'resolve'), | ||
params[1] && fixer.replaceText(params[1], 'reject') | ||
].filter(Boolean) | ||
} | ||
}) | ||
} | ||
@@ -17,0 +38,0 @@ } |
@@ -6,41 +6,60 @@ /** | ||
var errorMessage = 'Avoid callbacks. Prefer Async/Await.' | ||
'use strict' | ||
module.exports = function (context) { | ||
function checkLastParamsForCallback (node) { | ||
var len = node.params.length - 1 | ||
var lastParam = node.params[len] | ||
if (lastParam && (lastParam.name === 'callback' || lastParam.name === 'cb')) { | ||
context.report(lastParam, errorMessage) | ||
const getDocsUrl = require('./lib/get-docs-url') | ||
const errorMessage = 'Avoid callbacks. Prefer Async/Await.' | ||
module.exports = { | ||
meta: { | ||
docs: { | ||
url: getDocsUrl('prefer-await-to-callbacks') | ||
} | ||
} | ||
function isInsideYieldOrAwait () { | ||
return context.getAncestors().some(function (parent) { | ||
return parent.type === 'AwaitExpression' || parent.type === 'YieldExpression' | ||
}) | ||
} | ||
return { | ||
CallExpression: function (node) { | ||
// callbacks aren't allowed | ||
if (node.callee.name === 'cb' || node.callee.name === 'callback') { | ||
context.report(node, errorMessage) | ||
return | ||
}, | ||
create: function(context) { | ||
function checkLastParamsForCallback(node) { | ||
const len = node.params.length - 1 | ||
const lastParam = node.params[len] | ||
if ( | ||
lastParam && | ||
(lastParam.name === 'callback' || lastParam.name === 'cb') | ||
) { | ||
context.report({ node: lastParam, message: errorMessage }) | ||
} | ||
} | ||
function isInsideYieldOrAwait() { | ||
return context.getAncestors().some(function(parent) { | ||
return ( | ||
parent.type === 'AwaitExpression' || parent.type === 'YieldExpression' | ||
) | ||
}) | ||
} | ||
return { | ||
CallExpression: function(node) { | ||
// callbacks aren't allowed | ||
if (node.callee.name === 'cb' || node.callee.name === 'callback') { | ||
context.report({ node, message: errorMessage }) | ||
return | ||
} | ||
// thennables aren't allowed either | ||
var args = node.arguments | ||
var num = args.length - 1 | ||
var arg = num > -1 && node.arguments && node.arguments[num] | ||
if (arg && arg.type === 'FunctionExpression' || arg.type === 'ArrowFunctionExpression') { | ||
if (arg.params && arg.params[0] && arg.params[0].name === 'err') { | ||
if (!isInsideYieldOrAwait()) { | ||
context.report(arg, errorMessage) | ||
// thennables aren't allowed either | ||
const args = node.arguments | ||
const num = args.length - 1 | ||
const arg = num > -1 && node.arguments && node.arguments[num] | ||
if ( | ||
(arg && arg.type === 'FunctionExpression') || | ||
arg.type === 'ArrowFunctionExpression' | ||
) { | ||
if (arg.params && arg.params[0] && arg.params[0].name === 'err') { | ||
if (!isInsideYieldOrAwait()) { | ||
context.report({ node: arg, message: errorMessage }) | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
FunctionDeclaration: checkLastParamsForCallback, | ||
FunctionExpression: checkLastParamsForCallback, | ||
ArrowFunctionExpression: checkLastParamsForCallback | ||
}, | ||
FunctionDeclaration: checkLastParamsForCallback, | ||
FunctionExpression: checkLastParamsForCallback, | ||
ArrowFunctionExpression: checkLastParamsForCallback | ||
} | ||
} | ||
} |
@@ -6,15 +6,34 @@ /** | ||
module.exports = function (context) { | ||
return { | ||
MemberExpression: function (node) { | ||
// you can then() if you are inside of a yield or await | ||
if (context.getAncestors().some(function (parent) { | ||
return parent.type === 'AwaitExpression' || parent.type === 'YieldExpression' | ||
})) { | ||
return | ||
} | ||
'use strict' | ||
// if you're a then expression then you're probably a promise | ||
if (node.property && node.property.name === 'then') { | ||
context.report(node.property, 'Prefer await to then().') | ||
const getDocsUrl = require('./lib/get-docs-url') | ||
module.exports = { | ||
meta: { | ||
docs: { | ||
url: getDocsUrl('prefer-await-to-then') | ||
} | ||
}, | ||
create: function(context) { | ||
return { | ||
MemberExpression: function(node) { | ||
// you can then() if you are inside of a yield or await | ||
if ( | ||
context.getAncestors().some(function(parent) { | ||
return ( | ||
parent.type === 'AwaitExpression' || | ||
parent.type === 'YieldExpression' | ||
) | ||
}) | ||
) { | ||
return | ||
} | ||
// if you're a then expression then you're probably a promise | ||
if (node.property && node.property.name === 'then') { | ||
context.report({ | ||
node: node.property, | ||
message: 'Prefer await to then().' | ||
}) | ||
} | ||
} | ||
@@ -21,0 +40,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
36131
26
847
16
135
1