Skip to content

Commit 5be249c

Browse files
committed
New: no-restricted-disable rule
1 parent 400cea8 commit 5be249c

File tree

4 files changed

+256
-1
lines changed

4 files changed

+256
-1
lines changed

docs/rules/no-restricted-disable.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# disallows `eslint-disable` comments about specific rules (no-restricted-disable)
2+
3+
This rule warns `eslint-disable` directive-comments if the comment disable specific rules.
4+
5+
## Rule Details
6+
7+
:-1: Examples of **incorrect** code for `["no-undef", "no-unused-vars"]`:
8+
9+
```js
10+
/*eslint no-restricted-disable: ["error", "no-undef", "no-unused-vars"]*/
11+
12+
/*eslint-disable no-undef */
13+
f()
14+
```
15+
16+
```js
17+
/*eslint no-restricted-disable: ["error", "no-undef", "no-unused-vars"]*/
18+
19+
f() //eslint-disable-line no-undef
20+
```
21+
22+
```js
23+
/*eslint no-restricted-disable: ["error", "no-undef", "no-unused-vars"]*/
24+
25+
f() //eslint-disable-line
26+
```
27+
28+
:+1: Examples of **correct** code for this rule:
29+
30+
```js
31+
/*eslint no-restricted-disable: ["error", "no-undef", "no-unused-vars"]*/
32+
33+
f() //eslint-disable-line another-rule
34+
```
35+
36+
## Options
37+
38+
```json
39+
{
40+
"no-restricted-disable": ["error", ...]
41+
}
42+
```
43+
44+
This rule takes a list of strings, where each string is a glob pattern. For example:
45+
46+
```json
47+
{
48+
"no-restricted-disable": [
49+
"error",
50+
"no-undef",
51+
"*semi*", // rules which includes `semi`. E.g. `semi`, `semi-style`, `no-extra-semi`, ...
52+
"react/*" // rules of `eslint-plugin-react`
53+
]
54+
}
55+
```
56+
57+
```json
58+
{
59+
"no-restricted-disable": [
60+
"error",
61+
"*", // any rules
62+
"!no-console" // but except `no-console`.
63+
]
64+
}
65+
```

lib/rules/no-restricted-disable.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* @author Toru Nagashima
3+
* @copyright 2016 Toru Nagashima. All rights reserved.
4+
* See LICENSE file in root directory for full license.
5+
*/
6+
"use strict"
7+
8+
//------------------------------------------------------------------------------
9+
// Requirements
10+
//------------------------------------------------------------------------------
11+
12+
const Ignore = require("ignore")
13+
const DisabledArea = require("../disabled-area")
14+
const utils = require("../utils")
15+
16+
//------------------------------------------------------------------------------
17+
// Rule Definition
18+
//------------------------------------------------------------------------------
19+
20+
/**
21+
* Creates AST event handlers for no-restricted-disable.
22+
*
23+
* @param {RuleContext} context - The rule context.
24+
* @returns {object} AST event handlers.
25+
*/
26+
function create(context) {
27+
const sourceCode = context.getSourceCode()
28+
const disabledArea = DisabledArea.get(sourceCode)
29+
30+
if (context.options.length === 0) {
31+
return {}
32+
}
33+
34+
const ig = new Ignore()
35+
for (const pattern of context.options) {
36+
ig.add(pattern)
37+
}
38+
39+
return {
40+
Program() {
41+
for (const area of disabledArea.areas) {
42+
if (area.ruleId == null || ig.ignores(area.ruleId)) {
43+
context.report({
44+
loc: utils.toRuleIdLocation(area.comment, area.ruleId),
45+
message: "Disabling '{{ruleId}}' is not allowed.",
46+
data: { ruleId: area.ruleId || String(context.options) },
47+
})
48+
}
49+
}
50+
},
51+
}
52+
}
53+
54+
module.exports = {
55+
create,
56+
meta: {
57+
docs: {
58+
description: "disallows `eslint-disable` comments about specific rules",
59+
category: "Stylistic Issues",
60+
recommended: false,
61+
},
62+
fixable: false,
63+
schema: {
64+
type: "array",
65+
items: { type: "string" },
66+
uniqueItems: true,
67+
},
68+
},
69+
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"eslint": ">=4.7.0"
1414
},
1515
"dependencies": {
16-
"escape-string-regexp": "^1.0.5"
16+
"escape-string-regexp": "^1.0.5",
17+
"ignore": "^3.3.7"
1718
},
1819
"devDependencies": {
1920
"chokidar-cli": "^1.2.0",
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/**
2+
* @author Toru Nagashima
3+
* @copyright 2016 Toru Nagashima. All rights reserved.
4+
* See LICENSE file in root directory for full license.
5+
*/
6+
"use strict"
7+
8+
//------------------------------------------------------------------------------
9+
// Requirements
10+
//------------------------------------------------------------------------------
11+
12+
const RuleTester = require("eslint").RuleTester
13+
const rule = require("../../../lib/rules/no-restricted-disable")
14+
15+
//------------------------------------------------------------------------------
16+
// Tests
17+
//------------------------------------------------------------------------------
18+
19+
const tester = new RuleTester()
20+
21+
tester.run("no-restricted-disable", rule, {
22+
valid: [
23+
"/*eslint-disable*/",
24+
"//eslint-disable-line",
25+
"//eslint-disable-next-line",
26+
{
27+
code: "/*eslint-disable b*/",
28+
options: ["a"],
29+
},
30+
{
31+
code: "/*eslint-enable a*/",
32+
options: ["a"],
33+
},
34+
{
35+
code: "/*eslint-disable a*/",
36+
options: ["*", "!a"],
37+
},
38+
],
39+
invalid: [
40+
{
41+
code: "/*eslint-disable a*/",
42+
options: ["a"],
43+
errors: ["Disabling 'a' is not allowed."],
44+
},
45+
{
46+
code: "/*eslint-disable*/",
47+
options: ["a"],
48+
errors: ["Disabling 'a' is not allowed."],
49+
},
50+
{
51+
code: "//eslint-disable-line a",
52+
options: ["a"],
53+
errors: ["Disabling 'a' is not allowed."],
54+
},
55+
{
56+
code: "//eslint-disable-line",
57+
options: ["a"],
58+
errors: ["Disabling 'a' is not allowed."],
59+
},
60+
{
61+
code: "//eslint-disable-next-line a",
62+
options: ["a"],
63+
errors: ["Disabling 'a' is not allowed."],
64+
},
65+
{
66+
code: "//eslint-disable-next-line",
67+
options: ["a"],
68+
errors: ["Disabling 'a' is not allowed."],
69+
},
70+
71+
{
72+
code: "/*eslint-disable a, b, c*/",
73+
options: ["*", "!b", "!c"],
74+
errors: ["Disabling 'a' is not allowed."],
75+
},
76+
{
77+
code: "/*eslint-disable*/",
78+
options: ["*", "!b", "!c"],
79+
errors: ["Disabling '*,!b,!c' is not allowed."],
80+
},
81+
{
82+
code: "//eslint-disable-line a, b, c",
83+
options: ["*", "!b", "!c"],
84+
errors: ["Disabling 'a' is not allowed."],
85+
},
86+
{
87+
code: "//eslint-disable-line",
88+
options: ["*", "!b", "!c"],
89+
errors: ["Disabling '*,!b,!c' is not allowed."],
90+
},
91+
{
92+
code: "//eslint-disable-next-line a, b, c",
93+
options: ["*", "!b", "!c"],
94+
errors: ["Disabling 'a' is not allowed."],
95+
},
96+
{
97+
code: "//eslint-disable-next-line",
98+
options: ["*", "!b", "!c"],
99+
errors: ["Disabling '*,!b,!c' is not allowed."],
100+
},
101+
102+
{
103+
code: "/*eslint-disable semi, no-extra-semi, semi-style, comma-style*/",
104+
options: ["*semi*"],
105+
errors: [
106+
"Disabling 'semi' is not allowed.",
107+
"Disabling 'no-extra-semi' is not allowed.",
108+
"Disabling 'semi-style' is not allowed.",
109+
],
110+
},
111+
{
112+
code: "/*eslint-disable a, b, react/a, react/b*/",
113+
options: ["react/*"],
114+
errors: [
115+
"Disabling 'react/a' is not allowed.",
116+
"Disabling 'react/b' is not allowed.",
117+
],
118+
},
119+
],
120+
})

0 commit comments

Comments
 (0)