Skip to content

Commit

Permalink
New: no-restricted-properties rule (fixes eslint#3218)
Browse files Browse the repository at this point in the history
  • Loading branch information
willklein committed Oct 12, 2015
1 parent 54970cb commit 66202c8
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 0 deletions.
1 change: 1 addition & 0 deletions conf/eslint.json
Expand Up @@ -77,6 +77,7 @@
"no-redeclare": 2,
"no-regex-spaces": 2,
"no-restricted-modules": 0,
"no-restricted-properties": 0,
"no-restricted-syntax": 0,
"no-return-assign": 0,
"no-script-url": 0,
Expand Down
3 changes: 3 additions & 0 deletions docs/rules/README.md
Expand Up @@ -47,6 +47,8 @@ These are rules designed to prevent you from making mistakes. They either prescr
* [consistent-return](consistent-return.md) - require `return` statements to either always or never specify values
* [curly](curly.md) - specify curly brace conventions for all control statements
* [default-case](default-case.md) - require `default` case in `switch` statements
* [disallow-methods](disallow-methods.md) - disallow specified methods from being called on objects
* [dot-notation](dot-notation.md) - encourages use of dot notation whenever possible
* [dot-location](dot-location.md) - enforces consistent newlines before or after dots
* [dot-notation](dot-notation.md) - encourages use of dot notation whenever possible
* [eqeqeq](eqeqeq.md) - require the use of `===` and `!==` (fixable)
Expand Down Expand Up @@ -170,6 +172,7 @@ These rules are purely matters of style and are quite subjective.
* [no-negated-condition](no-negated-condition.md) - disallow negated conditions
* [no-nested-ternary](no-nested-ternary.md) - disallow nested ternary expressions
* [no-new-object](no-new-object.md) - disallow the use of the `Object` constructor
* [no-restricted-properties](no-restricted-properties.md) - restrict use of specified object properties
* [no-restricted-syntax](no-restricted-syntax.md) - disallow use of certain syntax in code
* [no-spaced-func](no-spaced-func.md) - disallow space between function identifier and application (fixable)
* [no-ternary](no-ternary.md) - disallow the use of ternary operators
Expand Down
73 changes: 73 additions & 0 deletions docs/rules/no-restricted-properties.md
@@ -0,0 +1,73 @@
# Restrict specified properties (no-restricted-properties)

Certain properties on objects may be disallowed in a codebase. This is useful for deprecating an API or restricting usage of a module's methods. This rule looks for accessing a given property key on a given object name, either when reading the property's value or invoking it as a function. You may specify an optional message to indicate an alternative API or a reason for the restriction.

## Rule Details

This rule is aimed at disallowing certain object properties from your code.

### Options

This rule takes a list of objects, where the object name and property names are specified:

```json
{
"rules": {
"no-restricted-properties": [2, {
"object": "disallowedObjectName",
"property": "disallowedPropertyName"
}]
}
}
```

Multiple object/property values can be disallowed, and you can specify an optional message:

```json
{
"rules": {
"no-restricted-properties": [2, {
"object": "disallowedObjectName",
"property": "disallowedPropertyName"
}, {
"object": "anotherDisallowedObjectName",
"property": "anotherDisallowedPropertyName",
"message": "anotherDisallowedObjectName.anotherDisallowedPropertyName is deprecated in favor of anotherDisallowedObjectName.newPropertyName"
}]
}
}
```

The following patterns are considered problems:

```js
/* eslint no-restricted-properties: [2, {
"object": "disallowedObjectName",
"property": "disallowedPropertyName"
}] */

var example = disallowedObjectName.disallowedPropertyName; /*error Disallowed object property: disallowedObjectName.disallowedPropertyName.*/

disallowedObjectName.disallowedPropertyName(); /*error Disallowed object property: disallowedObjectName.disallowedPropertyName.*/
```

The following patterns are not considered problems:

```js
/* eslint no-restricted-properties: [2, {
"object": "disallowedObjectName",
"property": "disallowedPropertyName"
}] */

var example = disallowedObjectName.somePropertyName;

someObjectName.disallowedPropertyName();
```

## When Not To Use It

If you don't have any object/property combinations to restrict, you should not use this rule.

## Related Rules

* [no-restricted-syntax](no-restricted-syntax.md)
29 changes: 29 additions & 0 deletions lib/rules/no-restricted-properties.js
@@ -0,0 +1,29 @@
/**
* @fileoverview Rule to disallow specified object methods
* @author Will Klein
* @copyright 2015 Will Klein. All rights reserved.
*/

"use strict";

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

module.exports = function(context) {
var restrictedProperties = context.options[0];

return {
"MemberExpression": function(node) {
restrictedProperties.forEach(function(restrictedProperty) {
var objectName = node.object && node.object.name;
var propertyName = node.property && node.property.name;

if (objectName === restrictedProperty.object &&
propertyName === restrictedProperty.property) {
context.report(node, "Using " + restrictedProperty.object + "." + restrictedProperty.property + " is disallowed");
}
});
}
};
};
75 changes: 75 additions & 0 deletions tests/lib/rules/no-restricted-properties.js
@@ -0,0 +1,75 @@
/**
* @fileoverview Tests for no-restricted-properties rule.
* @author Will Klein
* @copyright 2015 Will Klein. All rights reserved.
*/

"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

var rule = require("../../../lib/rules/no-restricted-properties");
var RuleTester = require("../../../lib/testers/rule-tester");

var ruleTester = new RuleTester();
ruleTester.run("no-restricted-properties", rule, {
valid: [
{
code: "someObject.someProperty",
options: [[{
object: "someObject",
property: "disallowedProperty"
}]]
}, {
code: "anotherObject.disallowedProperty",
options: [[{
object: "someObject",
property: "disallowedProperty"
}]]
}, {
code: "someObject.someProperty()",
options: [[{
object: "someObject",
property: "disallowedProperty"
}]]
}, {
code: "anotherObject.disallowedProperty()",
options: [[{
object: "someObject",
property: "disallowedProperty"
}]]
}
],

invalid: [
{
code: "someObject.disallowedProperty",
options: [[{
object: "someObject",
property: "disallowedProperty"
}]],
errors: [{
message: "Using someObject.disallowedProperty is disallowed",
type: "MemberExpression"
}]
}, {
code: "someObject.disallowedProperty; anotherObject.anotherDisallowedProperty()",
options: [[{
object: "someObject",
property: "disallowedProperty"
}, {
object: "anotherObject",
property: "anotherDisallowedProperty"
}]],
errors: [{
message: "Using someObject.disallowedProperty is disallowed",
type: "MemberExpression"
}, {
message: "Using anotherObject.anotherDisallowedProperty is disallowed",
type: "MemberExpression"
}]
}
]
});

0 comments on commit 66202c8

Please sign in to comment.