Skip to content

Commit

Permalink
feat: allow to define eslint-disable-next-line in multiple lines (#…
Browse files Browse the repository at this point in the history
…15436)

* feat: `eslint-disable-next-line` directive with multiple lines

* test: add cases for multiline `disable-next-line` directives

* test: add more cases

* fix: correct reporting location for unused disable directives

* docs: add examples for multiline eslint-disable-next-line directive

* fix: logic

* refactor: code

* refactor: rename `position` to `unprocessedDirective`
  • Loading branch information
snitin315 committed Dec 29, 2021
1 parent 51c37b1 commit 3b38018
Show file tree
Hide file tree
Showing 5 changed files with 338 additions and 27 deletions.
13 changes: 13 additions & 0 deletions docs/user-guide/configuring/rules.md
Expand Up @@ -200,6 +200,13 @@ alert('foo'); /* eslint-disable-line no-alert, quotes, semi */

/* eslint-disable-next-line no-alert, quotes, semi */
alert('foo');

/* eslint-disable-next-line
no-alert,
quotes,
semi
*/
alert('foo');
```

All of the above methods also work for plugin rules. For example, to disable `eslint-plugin-example`'s `rule-name` rule, combine the plugin's name (`example`) and the rule's name (`rule-name`) into `example/rule-name`:
Expand All @@ -214,6 +221,12 @@ Configuration comments can include descriptions to explain why the comment is ne
```js
// eslint-disable-next-line no-console -- Here's a description about why this configuration is necessary.
console.log('hello');

/* eslint-disable-next-line no-console --
* Here's a very long description about why this configuration is necessary
* along with some additional information
**/
console.log('hello');
```

**Note:** Comments that disable warnings for a portion of a file tell ESLint not to report rule violations for the disabled code. ESLint still parses the entire file, however, so disabled code still needs to be syntactically valid JavaScript.
Expand Down
36 changes: 20 additions & 16 deletions lib/linter/apply-disable-directives.js
Expand Up @@ -43,7 +43,7 @@ function groupByParentComment(directives) {
* Creates removal details for a set of directives within the same comment.
* @param {Directive[]} directives Unused directives to be removed.
* @param {Token} commentToken The backing Comment token.
* @returns {{ description, fix, position }[]} Details for later creation of output Problems.
* @returns {{ description, fix, unprocessedDirective }[]} Details for later creation of output Problems.
*/
function createIndividualDirectivesRemoval(directives, commentToken) {

Expand Down Expand Up @@ -138,7 +138,7 @@ function createIndividualDirectivesRemoval(directives, commentToken) {
],
text: ""
},
position: directive.unprocessedDirective
unprocessedDirective: directive.unprocessedDirective
};
});
}
Expand All @@ -147,7 +147,7 @@ function createIndividualDirectivesRemoval(directives, commentToken) {
* Creates a description of deleting an entire unused disable comment.
* @param {Directive[]} directives Unused directives to be removed.
* @param {Token} commentToken The backing Comment token.
* @returns {{ description, fix, position }} Details for later creation of an output Problem.
* @returns {{ description, fix, unprocessedDirective }} Details for later creation of an output Problem.
*/
function createCommentRemoval(directives, commentToken) {
const { range } = commentToken;
Expand All @@ -161,14 +161,14 @@ function createCommentRemoval(directives, commentToken) {
range,
text: " "
},
position: directives[0].unprocessedDirective
unprocessedDirective: directives[0].unprocessedDirective
};
}

/**
* Parses details from directives to create output Problems.
* @param {Directive[]} allDirectives Unused directives to be removed.
* @returns {{ description, fix, position }[]} Details for later creation of output Problems.
* @returns {{ description, fix, unprocessedDirective }[]} Details for later creation of output Problems.
*/
function processUnusedDisableDirectives(allDirectives) {
const directiveGroups = groupByParentComment(allDirectives);
Expand Down Expand Up @@ -261,17 +261,21 @@ function applyDirectives(options) {
const processed = processUnusedDisableDirectives(unusedDisableDirectivesToReport);

const unusedDisableDirectives = processed
.map(({ description, fix, position }) => ({
ruleId: null,
message: description
? `Unused eslint-disable directive (no problems were reported from ${description}).`
: "Unused eslint-disable directive (no problems were reported).",
line: position.line,
column: position.column,
severity: options.reportUnusedDisableDirectives === "warn" ? 1 : 2,
nodeType: null,
...options.disableFixes ? {} : { fix }
}));
.map(({ description, fix, unprocessedDirective }) => {
const { parentComment, type, line, column } = unprocessedDirective;

return {
ruleId: null,
message: description
? `Unused eslint-disable directive (no problems were reported from ${description}).`
: "Unused eslint-disable directive (no problems were reported).",
line: type === "disable-next-line" ? parentComment.commentToken.loc.start.line : line,
column: type === "disable-next-line" ? parentComment.commentToken.loc.start.column + 1 : column,
severity: options.reportUnusedDisableDirectives === "warn" ? 1 : 2,
nodeType: null,
...options.disableFixes ? {} : { fix }
};
});

return { problems, unusedDisableDirectives };
}
Expand Down
8 changes: 6 additions & 2 deletions lib/linter/linter.js
Expand Up @@ -305,7 +305,11 @@ function createDisableDirectives(options) {

// push to directives, if the rule is defined(including null, e.g. /*eslint enable*/)
if (ruleId === null || !!ruleMapper(ruleId)) {
result.directives.push({ parentComment, type, line: commentToken.loc.start.line, column: commentToken.loc.start.column + 1, ruleId });
if (type === "disable-next-line") {
result.directives.push({ parentComment, type, line: commentToken.loc.end.line, column: commentToken.loc.end.column + 1, ruleId });
} else {
result.directives.push({ parentComment, type, line: commentToken.loc.start.line, column: commentToken.loc.start.column + 1, ruleId });
}
} else {
result.directiveProblems.push(createLintingProblem({ ruleId, loc: commentToken.loc }));
}
Expand Down Expand Up @@ -368,7 +372,7 @@ function getDirectiveComments(ast, ruleMapper, warnInlineConfig) {
return;
}

if (lineCommentSupported && comment.loc.start.line !== comment.loc.end.line) {
if (directiveText === "eslint-disable-line" && comment.loc.start.line !== comment.loc.end.line) {
const message = `${directiveText} comment should not span multiple lines.`;

problems.push(createLintingProblem({
Expand Down
19 changes: 16 additions & 3 deletions tests/lib/linter/apply-disable-directives.js
Expand Up @@ -25,7 +25,20 @@ const applyDisableDirectives = require("../../../lib/linter/apply-disable-direct
*/
function createParentComment(range, value, ruleIds = []) {
return {
commentToken: { range, value },
commentToken: {
range,
loc: {
start: {
line: 1,
column: 1
},
end: {
line: 1,
column: value ? value.length : 10
}
},
value
},
ruleIds
};
}
Expand Down Expand Up @@ -1294,7 +1307,7 @@ describe("apply-disable-directives", () => {
parentComment: createParentComment([0, 27]),
type: "disable-next-line",
line: 1,
column: 1,
column: 2,
ruleId: null
}],
problems: [],
Expand All @@ -1305,7 +1318,7 @@ describe("apply-disable-directives", () => {
ruleId: null,
message: "Unused eslint-disable directive (no problems were reported).",
line: 1,
column: 1,
column: 2,
fix: {
range: [0, 27],
text: " "
Expand Down

0 comments on commit 3b38018

Please sign in to comment.