Skip to content
Permalink
Browse files

New: 'id-blacklist' rule (fixes #3358)

  • Loading branch information...
keithamus committed Jan 13, 2016
1 parent 2dba9c7 commit 5e4841e4be92876450fce7f87b733295c712f877
Showing with 496 additions and 0 deletions.
  1. +1 −0 conf/eslint.json
  2. +1 −0 docs/rules/README.md
  3. +83 −0 docs/rules/id-blacklist.md
  4. +110 −0 lib/rules/id-blacklist.js
  5. +301 −0 tests/lib/rules/id-blacklist.js
@@ -180,6 +180,7 @@
"quotes": 0,
"radix": 0,
"id-match": 0,
"id-blacklist": 0,
"require-jsdoc": 0,
"require-yield": 0,
"semi": 0,
@@ -157,6 +157,7 @@ These rules are purely matters of style and are quite subjective.
* [func-style](func-style.md) - enforce use of function declarations or expressions
* [id-length](id-length.md) - this option enforces minimum and maximum identifier lengths (variable names, property names etc.)
* [id-match](id-match.md) - require identifiers to match the provided regular expression
* [id-blacklist](id-blacklist.md) - blacklist certain identifiers to prevent them being used
* [indent](indent.md) - specify tab or space width for your code (fixable)
* [jsx-quotes](jsx-quotes.md) - specify whether double or single quotes should be used in JSX attributes
* [key-spacing](key-spacing.md) - enforce spacing between keys and values in object literal properties
@@ -0,0 +1,83 @@
# Blacklist certain identifiers to prevent them being used (id-blacklist)

> "There are only two hard things in Computer Science: cache invalidation and naming things." — Phil Karlton
Bad names can lead to hard to decipher code. Using generic names, such as `data` don't infer much about the code and the values it receives. This rule allows you to configure a blacklist of bad identifier names, that you don't want to see in your code.

## Rule Details

This rule compares assignments and function definitions to a provided list of identifier names. If the identifier is present in the list, it will return an error.

This rule will catch blacklisted identifiers that are:

- variable declarations
- function declarations
- object properties

It will not catch blacklisted identifiers that are:

- function calls (so you can still use functions you do not have control over)
- object properties (so you can still use objects you do not have control over)


### Options

This rule needs a a set of identifier names to blacklist, like so:

```json
{
"rules": {
"id-blacklist": [2, "data", "err", "e", "cb", "callback"]
}
}
```

For the rule in this example, the following patterns are considered problems:

```js
/*eslint id-blacklist: [2, "data", "err", "e", "cb", "callback"] */
var data = {...}; /*error Identifier 'data' is blacklisted*/
function callback() { /*error Identifier 'callback' is blacklisted*/
// ...
}
element.callback = function() { /*error Identifier 'callback' is blacklisted*/
// ...
};
var itemSet = {
data: [...] /*error Identifier 'data' is blacklisted*/
};
```

The following patterns are not considered problems:

```js
/*eslint id-blacklist: [2, "data", "err", "e", "cb", "callback"] */
var encodingOptions = {...};
function processFileResult() {
// ...
}
element.successHandler = function() {
// ...
};
var itemSet = {
entities: [...]
};
callback() // all function calls are ignored
foo.callback() // all function calls are ignored
foo.data // all property names that are not assignments are ignored
```

## When Not To Use It

You can turn this rule off if you are happy for identifiers to be named freely.
@@ -0,0 +1,110 @@
/**
* @fileoverview Rule that warns when identifier names that are
blacklisted in the configuration are used.
* @author Keith Cirkel (http://keithcirkel.co.uk)
* Based on id-match rule:
* @author Matthieu Larcher
* @copyright 2015 Matthieu Larcher. All rights reserved.
* See LICENSE in root directory for full license.
*/

"use strict";

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

module.exports = function(context) {


//--------------------------------------------------------------------------
// Helpers
//--------------------------------------------------------------------------

var blacklist = context.options;


/**
* Checks if a string matches the provided pattern
* @param {String} name The string to check.
* @returns {boolean} if the string is a match
* @private
*/
function isInvalid(name) {
return blacklist.indexOf(name) !== -1;
}

/**
* Verifies if we should report an error or not based on the effective
* parent node and the identifier name.
* @param {ASTNode} effectiveParent The effective parent node of the node to be reported
* @param {String} name The identifier name of the identifier node
* @returns {boolean} whether an error should be reported or not
*/
function shouldReport(effectiveParent, name) {
return effectiveParent.type !== "CallExpression"
&& effectiveParent.type !== "NewExpression" &&
isInvalid(name);
}

/**
* Reports an AST node as a rule violation.
* @param {ASTNode} node The node to report.
* @returns {void}
* @private
*/
function report(node) {
context.report(node, "Identifier '{{name}}' is blacklisted", {
name: node.name
});
}

return {

"Identifier": function(node) {
var name = node.name,
effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent;

// MemberExpressions get special rules
if (node.parent.type === "MemberExpression") {

// Always check object names
if (node.parent.object.type === "Identifier" &&
node.parent.object.name === node.name) {
if (isInvalid(name)) {
report(node);
}

// Report AssignmentExpressions only if they are the left side of the assignment
} else if (effectiveParent.type === "AssignmentExpression" &&
(effectiveParent.right.type !== "MemberExpression" ||
effectiveParent.left.type === "MemberExpression" &&
effectiveParent.left.property.name === node.name)) {
if (isInvalid(name)) {
report(node);
}
}

// Properties have their own rules
} else if (node.parent.type === "Property") {

if (shouldReport(effectiveParent, name)) {
report(node);
}

// Report anything that is a match and not a CallExpression
} else if (shouldReport(effectiveParent, name)) {
report(node);
}
}

};

};
module.exports.schema = {
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true
};
Oops, something went wrong.

0 comments on commit 5e4841e

Please sign in to comment.
You can’t perform that action at this time.