diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..3420abf9 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,19 @@ +{ + "env": { + "node": true + }, + "parserOptions": { + "ecmaVersion": 6 + }, + "plugins": [ + "eslint-plugin" + ], + "rules": { + "eslint-plugin/require-meta-docs-url": [ + "error", + { + "pattern": "https://github.com/xjamundx/eslint-plugin-promise#{{name}}" + } + ] + } +} diff --git a/.npmignore b/.npmignore index d372db87..7297979a 100644 --- a/.npmignore +++ b/.npmignore @@ -3,3 +3,4 @@ node_modules test .npmignore .travis.yml +.eslintrc.json diff --git a/.travis.yml b/.travis.yml index de50a1f7..0d2a4ddf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,3 +3,6 @@ node_js: - 4 - 6 - 8 +script: + - npm run test + - npm run lint diff --git a/package.json b/package.json index 66a01df3..91fa017f 100644 --- a/package.json +++ b/package.json @@ -13,10 +13,12 @@ "repository": "git@github.com:xjamundx/eslint-plugin-promise.git", "scripts": { "pretest": "standard", - "test": "mocha test" + "test": "mocha test", + "lint": "eslint index.js rules test" }, "devDependencies": { "eslint": "^4.17.0", + "eslint-plugin-eslint-plugin": "^1.4.0", "mocha": "^5.0.0", "standard": "^7.1.2" }, diff --git a/rules/always-return.js b/rules/always-return.js index e1792492..d595184b 100644 --- a/rules/always-return.js +++ b/rules/always-return.js @@ -55,6 +55,11 @@ function peek (arr) { } module.exports = { + meta: { + docs: { + url: 'https://github.com/xjamundx/eslint-plugin-promise#always-return' + } + }, create: function (context) { // funcInfoStack is a stack representing the stack of currently executing // functions diff --git a/rules/avoid-new.js b/rules/avoid-new.js index d82486d6..f7560aac 100644 --- a/rules/avoid-new.js +++ b/rules/avoid-new.js @@ -5,11 +5,18 @@ 'use strict' -module.exports = function (context) { - return { - NewExpression: function (node) { - if (node.callee.name === 'Promise') { - context.report(node, 'Avoid creating new promises.') +module.exports = { + meta: { + docs: { + url: 'https://github.com/xjamundx/eslint-plugin-promise#avoid-new' + } + }, + create: function (context) { + return { + NewExpression: function (node) { + if (node.callee.name === 'Promise') { + context.report(node, 'Avoid creating new promises.') + } } } } diff --git a/rules/catch-or-return.js b/rules/catch-or-return.js index 49380238..e58d54a1 100644 --- a/rules/catch-or-return.js +++ b/rules/catch-or-return.js @@ -9,6 +9,11 @@ var isPromise = require('./lib/is-promise') module.exports = { + meta: { + docs: { + url: 'https://github.com/xjamundx/eslint-plugin-promise#catch-or-return' + } + }, create: function (context) { var options = context.options[0] || {} var allowThen = options.allowThen diff --git a/rules/lib/.eslintrc.json b/rules/lib/.eslintrc.json new file mode 100644 index 00000000..ee242439 --- /dev/null +++ b/rules/lib/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "rules": { + "eslint-plugin/require-meta-docs-url": "off" + } +} diff --git a/rules/no-callback-in-promise.js b/rules/no-callback-in-promise.js index 740d9caa..19c0b1de 100644 --- a/rules/no-callback-in-promise.js +++ b/rules/no-callback-in-promise.js @@ -9,24 +9,31 @@ var hasPromiseCallback = require('./lib/has-promise-callback') var isInsidePromise = require('./lib/is-inside-promise') var isCallback = require('./lib/is-callback') -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.') +module.exports = { + meta: { + docs: { + url: 'https://github.com/xjamundx/eslint-plugin-promise#no-callback-in-promise' + } + }, + create: 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.') + } } + return + } + if (context.getAncestors().some(isInsidePromise)) { + context.report(node, 'Avoid calling back inside of a promise.') } - return - } - if (context.getAncestors().some(isInsidePromise)) { - context.report(node, 'Avoid calling back inside of a promise.') } } } diff --git a/rules/no-native.js b/rules/no-native.js index eefd3be6..4c4dbd0c 100644 --- a/rules/no-native.js +++ b/rules/no-native.js @@ -18,6 +18,11 @@ function isDeclared (scope, ref) { } module.exports = { + meta: { + docs: { + url: 'https://github.com/xjamundx/eslint-plugin-promise#no-native' + } + }, create: function (context) { var MESSAGE = '"{{name}}" is not defined.' diff --git a/rules/no-nesting.js b/rules/no-nesting.js index d3a38a66..884544b1 100644 --- a/rules/no-nesting.js +++ b/rules/no-nesting.js @@ -8,12 +8,19 @@ var hasPromiseCallback = require('./lib/has-promise-callback') var isInsidePromise = require('./lib/is-inside-promise') -module.exports = function (context) { - return { - CallExpression: function (node) { - if (!hasPromiseCallback(node)) return - if (context.getAncestors().some(isInsidePromise)) { - context.report(node, 'Avoid nesting promises.') +module.exports = { + meta: { + docs: { + url: 'https://github.com/xjamundx/eslint-plugin-promise#no-nesting' + } + }, + create: function (context) { + return { + CallExpression: function (node) { + if (!hasPromiseCallback(node)) return + if (context.getAncestors().some(isInsidePromise)) { + context.report(node, 'Avoid nesting promises.') + } } } } diff --git a/rules/no-promise-in-callback.js b/rules/no-promise-in-callback.js index ee674eb3..f7fde0ba 100644 --- a/rules/no-promise-in-callback.js +++ b/rules/no-promise-in-callback.js @@ -8,20 +8,27 @@ var isPromise = require('./lib/is-promise') var isInsideCallback = require('./lib/is-inside-callback') -module.exports = function (context) { - return { - CallExpression: function (node) { - if (!isPromise(node)) return +module.exports = { + meta: { + docs: { + url: 'https://github.com/xjamundx/eslint-plugin-promise#no-promise-in-callback' + } + }, + create: function (context) { + return { + CallExpression: function (node) { + if (!isPromise(node)) 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 i'm returning the promise, it's probably not really a callback + // function, and I should be okay.... + if (node.parent.type === 'ReturnStatement') return - // what about if the parent is an ArrowFunctionExpression - // would that imply an implicit return? + // what about if the parent is an ArrowFunctionExpression + // would that imply an implicit return? - if (context.getAncestors().some(isInsideCallback)) { - context.report(node.callee, 'Avoid using promises inside of callbacks.') + if (context.getAncestors().some(isInsideCallback)) { + context.report(node.callee, 'Avoid using promises inside of callbacks.') + } } } } diff --git a/rules/no-return-in-finally.js b/rules/no-return-in-finally.js index ddefb5cf..f0ecaedb 100644 --- a/rules/no-return-in-finally.js +++ b/rules/no-return-in-finally.js @@ -3,6 +3,11 @@ var isPromise = require('./lib/is-promise') module.exports = { + meta: { + docs: { + url: 'https://github.com/xjamundx/eslint-plugin-promise#no-return-in-finally' + } + }, create: function (context) { return { CallExpression: function (node) { diff --git a/rules/no-return-wrap.js b/rules/no-return-wrap.js index 849c3f3e..0c1624cd 100644 --- a/rules/no-return-wrap.js +++ b/rules/no-return-wrap.js @@ -18,6 +18,11 @@ function isInPromise (context) { } module.exports = { + meta: { + docs: { + url: 'https://github.com/xjamundx/eslint-plugin-promise#no-return-wrap' + } + }, create: function (context) { var options = context.options[0] || {} var allowReject = options.allowReject diff --git a/rules/param-names.js b/rules/param-names.js index 834f542b..0da8315c 100644 --- a/rules/param-names.js +++ b/rules/param-names.js @@ -1,6 +1,11 @@ 'use strict' module.exports = { + meta: { + docs: { + url: 'https://github.com/xjamundx/eslint-plugin-promise#param-names' + } + }, create: function (context) { return { NewExpression: function (node) { diff --git a/rules/prefer-await-to-callbacks.js b/rules/prefer-await-to-callbacks.js index 652f1066..b4eb59f8 100644 --- a/rules/prefer-await-to-callbacks.js +++ b/rules/prefer-await-to-callbacks.js @@ -7,41 +7,48 @@ var errorMessage = 'Avoid callbacks. Prefer Async/Await.' -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) +module.exports = { + meta: { + docs: { + url: 'https://github.com/xjamundx/eslint-plugin-promise#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) { + var len = node.params.length - 1 + var lastParam = node.params[len] + if (lastParam && (lastParam.name === 'callback' || lastParam.name === 'cb')) { + context.report(lastParam, 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, 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 + 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) + } } } - } - }, - FunctionDeclaration: checkLastParamsForCallback, - FunctionExpression: checkLastParamsForCallback, - ArrowFunctionExpression: checkLastParamsForCallback + }, + FunctionDeclaration: checkLastParamsForCallback, + FunctionExpression: checkLastParamsForCallback, + ArrowFunctionExpression: checkLastParamsForCallback + } } } diff --git a/rules/prefer-await-to-then.js b/rules/prefer-await-to-then.js index 28fe92b3..2f7ef6b3 100644 --- a/rules/prefer-await-to-then.js +++ b/rules/prefer-await-to-then.js @@ -5,19 +5,26 @@ 'use strict' -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 - } +module.exports = { + meta: { + docs: { + url: 'https://github.com/xjamundx/eslint-plugin-promise#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.property, 'Prefer await to then().') + // 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().') + } } } }