From 04c7005bac0da4a02b54c4e0cde8a607400f9016 Mon Sep 17 00:00:00 2001 From: Jamund Ferguson Date: Wed, 25 May 2016 09:18:04 -0700 Subject: [PATCH] no-native rule --- README.md | 18 ++++++++++++++++++ index.js | 1 + rules/no-native.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ test/no-native.js | 23 +++++++++++++++++++++++ 4 files changed, 87 insertions(+) create mode 100644 rules/no-native.js create mode 100644 test/no-native.js diff --git a/README.md b/README.md index b5721d02..eb7b9222 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,23 @@ 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("blubird"); +var x = Promise.resolve("good"); +``` + +#### Invalid +```js +var x = Promise.resolve("bad"); +``` ## Installation @@ -127,6 +144,7 @@ Then configure the rules you want to use under the rules section. "promise/always-return": 2, "promise/always-catch": 2, // deprecated "promise/catch-or-return": 2, + "promise/no-native": 0, } } ``` diff --git a/index.js b/index.js index ad7862b3..9bf455bf 100644 --- a/index.js +++ b/index.js @@ -9,6 +9,7 @@ module.exports = { 'param-names': 1, 'always-return': 1, 'always-catch': 1, + 'no-native': 0, 'catch-or-return': 1 } } diff --git a/rules/no-native.js b/rules/no-native.js new file mode 100644 index 00000000..f5193804 --- /dev/null +++ b/rules/no-native.js @@ -0,0 +1,45 @@ +// Borrowed from here: +// https://github.com/colonyamerican/eslint-plugin-cah/issues/3 + +'use strict' + +module.exports = function (context) { + var MESSAGE = '"{{name}}" is not defined.' + + /** + * Checks for and reports reassigned constants + * + * @param {Scope} scope - an escope Scope object + * @returns {void} + * @private + */ + function isDeclared (scope, ref) { + return scope.variables.some(function (variable) { + if (variable.name !== ref.identifier.name) { + return false + } + + if (!variable.defs || !variable.defs.length) { + return false + } + + return true + }) + } + + return { + 'Program:exit': function () { + var scope = context.getScope() + + scope.through.forEach(function (ref) { + if (ref.identifier.name !== 'Promise') { + return + } + + if (!isDeclared(scope, ref)) { + context.report(ref.identifier, MESSAGE, { name: ref.identifier.name }) + } + }) + } + } +} diff --git a/test/no-native.js b/test/no-native.js new file mode 100644 index 00000000..baef4035 --- /dev/null +++ b/test/no-native.js @@ -0,0 +1,23 @@ +'use strict' + +var rule = require('../rules/no-native') +var RuleTester = require('eslint').RuleTester + +var ruleTester = new RuleTester() +ruleTester.run('no-native', rule, { + valid: [ + 'var Promise = null; function x() { return Promise.resolve("hi"); }', + 'var Promise = window.Promise || require("bluebird"); var x = Promise.reject();' + ], + + invalid: [ + { + code: 'new Promise(function(reject, resolve) { })', + errors: [ { message: '"Promise" is not defined.' } ] + }, + { + code: 'Promise.resolve()', + errors: [ { message: '"Promise" is not defined.' } ] + } + ] +})