Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6f91f60
commit d67bfdd
Showing
8 changed files
with
224 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# Disallow Unused Labels (no-unused-labels) | ||
|
||
Labels that are declared and not used anywhere in the code are most likely an error due to incomplete refactoring. | ||
|
||
```js | ||
OUTER_LOOP: | ||
for (const student of students) { | ||
if (checkScores(student.scores)) { | ||
continue; | ||
} | ||
doSomething(student); | ||
} | ||
``` | ||
|
||
In this case, probably removing `OUTER_LOOP:` had been forgotten. | ||
Such labels take up space in the code and can lead to confusion by readers. | ||
|
||
## Rule Details | ||
|
||
This rule is aimed at eliminating unused labels. | ||
|
||
The following patterns are considered problems: | ||
|
||
```js | ||
/*eslint no-unused-labels: 2*/ | ||
|
||
A: var foo = 0; /*error 'A:' is defined but never used.*/ | ||
|
||
B: { /*error 'B:' is defined but never used.*/ | ||
foo(); | ||
} | ||
|
||
C: /*error 'C:' is defined but never used.*/ | ||
for (let i = 0; i < 10; ++i) { | ||
foo(); | ||
} | ||
``` | ||
|
||
The following patterns are considered not problems: | ||
|
||
```js | ||
/*eslint no-unused-labels: 2*/ | ||
|
||
A: { | ||
if (foo()) { | ||
break A; | ||
} | ||
bar(); | ||
} | ||
|
||
B: | ||
for (let i = 0; i < 10; ++i) { | ||
if (foo()) { | ||
break B; | ||
} | ||
bar(); | ||
} | ||
``` | ||
|
||
## When Not To Use It | ||
|
||
If you don't want to be notified about unused labels, then it's safe to disable this rule. | ||
|
||
## Related Rules | ||
|
||
* [no-empty-label](./no-empty-label.md) | ||
* [no-labels](./no-labels.md) | ||
* [no-label-var](./no-label-var.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/** | ||
* @fileoverview Rule to disallow unused labels. | ||
* @author Toru Nagashima | ||
* @copyright 2016 Toru Nagashima. All rights reserved. | ||
* See LICENSE file in root directory for full license. | ||
*/ | ||
|
||
"use strict"; | ||
|
||
//------------------------------------------------------------------------------ | ||
// Rule Definition | ||
//------------------------------------------------------------------------------ | ||
|
||
module.exports = function(context) { | ||
var scopeInfo = null; | ||
|
||
/** | ||
* Adds a scope info to the stack. | ||
* | ||
* @param {ASTNode} node - A node to add. This is a LabeledStatement. | ||
* @returns {void} | ||
*/ | ||
function enterLabeledScope(node) { | ||
scopeInfo = { | ||
label: node.label.name, | ||
used: false, | ||
upper: scopeInfo | ||
}; | ||
} | ||
|
||
/** | ||
* Removes the top of the stack. | ||
* At the same time, this reports the label if it's never used. | ||
* | ||
* @param {ASTNode} node - A node to report. This is a LabeledStatement. | ||
* @returns {void} | ||
*/ | ||
function exitLabeledScope(node) { | ||
if (!scopeInfo.used) { | ||
context.report({ | ||
node: node.label, | ||
message: "'{{name}}:' is defined but never used.", | ||
data: node.label | ||
}); | ||
} | ||
|
||
scopeInfo = scopeInfo.upper; | ||
} | ||
|
||
/** | ||
* Marks the label of a given node as used. | ||
* | ||
* @param {ASTNode} node - A node to mark. This is a BreakStatement or | ||
* ContinueStatement. | ||
* @returns {void} | ||
*/ | ||
function markAsUsed(node) { | ||
if (!node.label) { | ||
return; | ||
} | ||
|
||
var label = node.label.name; | ||
var info = scopeInfo; | ||
while (info) { | ||
if (info.label === label) { | ||
info.used = true; | ||
break; | ||
} | ||
info = info.upper; | ||
} | ||
} | ||
|
||
return { | ||
"LabeledStatement": enterLabeledScope, | ||
"LabeledStatement:exit": exitLabeledScope, | ||
"BreakStatement": markAsUsed, | ||
"ContinueStatement": markAsUsed | ||
}; | ||
}; | ||
|
||
module.exports.schema = []; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/** | ||
* @fileoverview Tests for no-unused-labels rule. | ||
* @author Toru Nagashima | ||
* @copyright 2016 Toru Nagashima. All rights reserved. | ||
* See LICENSE file in root directory for full license. | ||
*/ | ||
|
||
"use strict"; | ||
|
||
//------------------------------------------------------------------------------ | ||
// Requirements | ||
//------------------------------------------------------------------------------ | ||
|
||
var rule = require("../../../lib/rules/no-unused-labels"), | ||
RuleTester = require("../../../lib/testers/rule-tester"); | ||
|
||
//------------------------------------------------------------------------------ | ||
// Tests | ||
//------------------------------------------------------------------------------ | ||
|
||
var ruleTester = new RuleTester(); | ||
ruleTester.run("no-unused-labels", rule, { | ||
valid: [ | ||
"A: break A;", | ||
"A: { foo(); break A; bar(); }", | ||
"A: if (a) { foo(); if (b) break A; bar(); }", | ||
"A: for (var i = 0; i < 10; ++i) { foo(); if (a) break A; bar(); }", | ||
"A: for (var i = 0; i < 10; ++i) { foo(); if (a) continue A; bar(); }", | ||
"A: { B: break B; C: for (var i = 0; i < 10; ++i) { foo(); if (a) break A; if (c) continue C; bar(); } }", | ||
"A: { var A = 0; console.log(A); break A; console.log(A); }" | ||
], | ||
invalid: [ | ||
{code: "A: var foo = 0;", errors: ["'A:' is defined but never used."]}, | ||
{code: "A: { foo(); bar(); }", errors: ["'A:' is defined but never used."]}, | ||
{code: "A: if (a) { foo(); bar(); }", errors: ["'A:' is defined but never used."]}, | ||
{code: "A: for (var i = 0; i < 10; ++i) { foo(); if (a) break; bar(); }", errors: ["'A:' is defined but never used."]}, | ||
{code: "A: for (var i = 0; i < 10; ++i) { foo(); if (a) continue; bar(); }", errors: ["'A:' is defined but never used."]}, | ||
{code: "A: for (var i = 0; i < 10; ++i) { B: break A; }", errors: ["'B:' is defined but never used."]}, | ||
{code: "A: { var A = 0; console.log(A); }", errors: ["'A:' is defined but never used."]} | ||
|
||
// Below is fatal errors. | ||
// "A: break B", | ||
// "A: function foo() { break A; }", | ||
// "A: class Foo { foo() { break A; } }", | ||
// "A: { A: { break A; } }" | ||
] | ||
}); |