Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make no-unused-disable fixable #13

Merged
merged 1 commit into from
Feb 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/rules/no-unused-disable.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# disallow unused `eslint-disable` comments (eslint-comments/no-unused-disable)
# disallows unused `eslint-disable` comments (eslint-comments/no-unused-disable)

- ✒️ This rule is fixable. The fixer removes the comment. Note that it removes the entire comment, even if multiple rules were disabled, and only one was unused, which is likely undesirable.

Since refactoring or a bug fix of upstream, an `eslint-disable` directive-comment may become unnecessary.
In that case, you should remove the garbage as soon as possible since the garbage may cause to overlook ESLint warnings in future.
Expand Down
2 changes: 1 addition & 1 deletion lib/rules/no-unused-disable.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module.exports = {
url:
"https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/no-unused-disable.html",
},
fixable: null,
fixable: "code",
schema: [],
},

Expand Down
11 changes: 11 additions & 0 deletions lib/utils/patch.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ function createNoUnusedDisableError(ruleId, severity, message, comment) {
clone.endLine = comment.loc.end.line
clone.endColumn = comment.loc.end.column + 1
}

// Remove the whole node if it is the only rule, otherwise
// don't try to fix because it is quite complicated.
if (!comment.value.includes(",")) {
// We can't use the typical `fixer` helper because we are injecting
// this message after the fixes are resolved.
clone.fix = {
range: comment.range,
text: comment.value.includes("\n") ? "\n" : "",
}
}
}

return clone
Expand Down
134 changes: 117 additions & 17 deletions tests/lib/rules/no-unused-disable.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,13 @@ function baz() {
})

describe("invalid", () => {
for (const { code, errors, reportUnusedDisableDirectives } of [
for (const testCase of [
{
title: "Generic same line",
code: `/*eslint no-undef:off*/
var a = b //eslint-disable-line`,
output: `/*eslint no-undef:off*/
var a = b `,
errors: [
{
message:
Expand All @@ -159,8 +162,11 @@ var a = b //eslint-disable-line`,
],
},
{
title: "Specific same line",
code: `/*eslint no-undef:off*/
var a = b //eslint-disable-line no-undef`,
output: `/*eslint no-undef:off*/
var a = b `,
errors: [
{
message:
Expand All @@ -173,6 +179,7 @@ var a = b //eslint-disable-line no-undef`,
],
},
{
title: "Multiple in a same line",
code: `/*eslint no-undef:off, no-unused-vars:off*/
var a = b //eslint-disable-line no-undef,no-unused-vars`,
errors: [
Expand All @@ -195,8 +202,12 @@ var a = b //eslint-disable-line no-undef,no-unused-vars`,
],
},
{
title: "Generic next line",
code: `/*eslint no-undef:off*/
//eslint-disable-next-line
var a = b`,
output: `/*eslint no-undef:off*/

var a = b`,
errors: [
{
Expand All @@ -210,8 +221,12 @@ var a = b`,
],
},
{
title: "Specific next line",
code: `/*eslint no-undef:off*/
//eslint-disable-next-line no-undef
var a = b`,
output: `/*eslint no-undef:off*/

var a = b`,
errors: [
{
Expand All @@ -225,6 +240,7 @@ var a = b`,
],
},
{
title: "Multiple next line",
code: `/*eslint no-undef:off, no-unused-vars:off*/
//eslint-disable-next-line no-undef,no-unused-vars
var a = b`,
Expand All @@ -248,8 +264,12 @@ var a = b`,
],
},
{
title: "Generic block",
code: `/*eslint no-undef:off*/
/*eslint-disable*/
var a = b`,
output: `/*eslint no-undef:off*/

var a = b`,
errors: [
{
Expand All @@ -263,8 +283,29 @@ var a = b`,
],
},
{
title: "Replaces multi-line block comments with a newline",
code: `foo/* eslint-disable
*/ bar`,
output: `foo
bar`,
errors: [
{
message:
"ESLint rules are disabled but never reported.",
line: 1,
column: 4,
endLine: 2,
endColumn: 3,
},
],
},
{
title: "Specific block",
code: `/*eslint no-undef:off*/
/*eslint-disable no-undef*/
var a = b`,
output: `/*eslint no-undef:off*/

var a = b`,
errors: [
{
Expand All @@ -278,6 +319,7 @@ var a = b`,
],
},
{
title: "Multiple block",
code: `/*eslint no-undef:off, no-unused-vars:off*/
/*eslint-disable no-undef,no-unused-vars*/
var a = b`,
Expand All @@ -301,8 +343,13 @@ var a = b`,
],
},
{
title: "Generic block with enable after",
code: `/*eslint no-undef:off*/
/*eslint-disable*/
var a = b
/*eslint-enable*/`,
output: `/*eslint no-undef:off*/

var a = b
/*eslint-enable*/`,
errors: [
Expand All @@ -317,8 +364,13 @@ var a = b
],
},
{
title: "Specific block with enable after",
code: `/*eslint no-undef:off*/
/*eslint-disable no-undef*/
var a = b
/*eslint-enable*/`,
output: `/*eslint no-undef:off*/

var a = b
/*eslint-enable*/`,
errors: [
Expand All @@ -333,6 +385,7 @@ var a = b
],
},
{
title: "Multiple block with enable after",
code: `/*eslint no-undef:off, no-unused-vars:off*/
/*eslint-disable no-undef,no-unused-vars*/
var a = b
Expand All @@ -357,8 +410,13 @@ var a = b
],
},
{
title: "Generic block disable with no error inside",
code: `/*eslint no-undef:error*/
/*eslint-disable*/
/*eslint-enable*/
var a = b//eslint-disable-line no-undef`,
output: `/*eslint no-undef:error*/

/*eslint-enable*/
var a = b//eslint-disable-line no-undef`,
errors: [
Expand All @@ -373,8 +431,13 @@ var a = b//eslint-disable-line no-undef`,
],
},
{
title: "Specific block disable with no error inside",
code: `/*eslint no-undef:error*/
/*eslint-disable no-undef*/
/*eslint-enable no-undef*/
var a = b//eslint-disable-line no-undef`,
output: `/*eslint no-undef:error*/

/*eslint-enable no-undef*/
var a = b//eslint-disable-line no-undef`,
errors: [
Expand All @@ -389,6 +452,7 @@ var a = b//eslint-disable-line no-undef`,
],
},
{
title: "Multiple specific block disable with no error inside",
code: `/*eslint no-undef:error, no-unused-vars:error*/
/*eslint-disable no-undef,no-unused-vars*/
/*eslint-enable no-undef*/
Expand All @@ -405,6 +469,8 @@ var a = b//eslint-disable-line no-undef`,
],
},
{
title:
"Multiple specific block disable with only one error inside",
code: `/*eslint no-undef:error, no-unused-vars:error*/
/*eslint-disable
no-undef,
Expand All @@ -424,8 +490,10 @@ var a = b
],
},
{
title: "Specific block disable at end of input",
code:
"/* eslint new-parens:error*/ /*eslint-disable new-parens*/",
output: "/* eslint new-parens:error*/ ",
errors: [
{
message:
Expand All @@ -438,8 +506,11 @@ var a = b
],
},
{
title: "Generic same line with rule off",
code: `/*eslint no-undef:off*/
var a = b //eslint-disable-line`,
output: `/*eslint no-undef:off*/
var a = b `,
errors: [
{
message:
Expand All @@ -457,8 +528,11 @@ var a = b //eslint-disable-line`,
reportUnusedDisableDirectives: true,
},
{
title: "Specific same line with rule off",
code: `/*eslint no-undef:off*/
var a = b //eslint-disable-line no-undef`,
output: `/*eslint no-undef:off*/
var a = b `,
errors: [
{
message:
Expand All @@ -476,8 +550,8 @@ var a = b //eslint-disable-line no-undef`,
reportUnusedDisableDirectives: true,
},

// Don't crash even if the source code has a parse error.
{
title: "Don't crash even if the source code has a parse error",
code:
"/*eslint no-undef:error*/\nvar a = b c //eslint-disable-line no-undef",
errors: [
Expand All @@ -487,24 +561,50 @@ var a = b //eslint-disable-line no-undef`,
],
},
]) {
it(code, () =>
runESLint(code, reportUnusedDisableDirectives).then(
actualMessages => {
assert.strictEqual(actualMessages.length, errors.length)
for (let i = 0; i < errors.length; ++i) {
const actual = actualMessages[i]
const expected = errors[i]
it(testCase.title || testCase.code, () =>
runESLint(
testCase.code,
testCase.reportUnusedDisableDirectives
).then(actualMessages => {
assert.strictEqual(
actualMessages.length,
testCase.errors.length
)

let actualOutput = testCase.code

for (const key of Object.keys(expected)) {
assert.strictEqual(
actual[key],
expected[key],
`'${key}' is not expected.`
)
}
for (let i = 0; i < testCase.errors.length; ++i) {
const actual = actualMessages[i]
const expected = testCase.errors[i]

// We need to duplicate the simple logic in ESLint's
// source-code-fixer.js to apply the fix. If we run
// ESLint with --fix-dry-run, it won't report any
// errors since it would have fixed them.
if (actual.fix) {
actualOutput =
actualOutput.slice(0, actual.fix.range[0]) +
actual.fix.text +
actualOutput.slice(actual.fix.range[1])
}

for (const key of Object.keys(expected)) {
assert.strictEqual(
actual[key],
expected[key],
`'${key}' is not expected.`
)
}
}

if (testCase.output) {
assert.strictEqual(
actualOutput,
testCase.output,
"output is not expected"
)
}
)
})
)
}
})
Expand Down