diff options
Diffstat (limited to 'tools/node_modules/eslint/lib/rules/no-extra-label.js')
-rw-r--r-- | tools/node_modules/eslint/lib/rules/no-extra-label.js | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/tools/node_modules/eslint/lib/rules/no-extra-label.js b/tools/node_modules/eslint/lib/rules/no-extra-label.js new file mode 100644 index 0000000000..b89267de93 --- /dev/null +++ b/tools/node_modules/eslint/lib/rules/no-extra-label.js @@ -0,0 +1,140 @@ +/** + * @fileoverview Rule to disallow unnecessary labels + * @author Toru Nagashima + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "disallow unnecessary labels", + category: "Best Practices", + recommended: false + }, + + schema: [], + + fixable: "code" + }, + + create(context) { + const sourceCode = context.getSourceCode(); + let scopeInfo = null; + + /** + * Creates a new scope with a breakable statement. + * + * @param {ASTNode} node - A node to create. This is a BreakableStatement. + * @returns {void} + */ + function enterBreakableStatement(node) { + scopeInfo = { + label: node.parent.type === "LabeledStatement" ? node.parent.label : null, + breakable: true, + upper: scopeInfo + }; + } + + /** + * Removes the top scope of the stack. + * + * @returns {void} + */ + function exitBreakableStatement() { + scopeInfo = scopeInfo.upper; + } + + /** + * Creates a new scope with a labeled statement. + * + * This ignores it if the body is a breakable statement. + * In this case it's handled in the `enterBreakableStatement` function. + * + * @param {ASTNode} node - A node to create. This is a LabeledStatement. + * @returns {void} + */ + function enterLabeledStatement(node) { + if (!astUtils.isBreakableStatement(node.body)) { + scopeInfo = { + label: node.label, + breakable: false, + upper: scopeInfo + }; + } + } + + /** + * Removes the top scope of the stack. + * + * This ignores it if the body is a breakable statement. + * In this case it's handled in the `exitBreakableStatement` function. + * + * @param {ASTNode} node - A node. This is a LabeledStatement. + * @returns {void} + */ + function exitLabeledStatement(node) { + if (!astUtils.isBreakableStatement(node.body)) { + scopeInfo = scopeInfo.upper; + } + } + + /** + * Reports a given control node if it's unnecessary. + * + * @param {ASTNode} node - A node. This is a BreakStatement or a + * ContinueStatement. + * @returns {void} + */ + function reportIfUnnecessary(node) { + if (!node.label) { + return; + } + + const labelNode = node.label; + + for (let info = scopeInfo; info !== null; info = info.upper) { + if (info.breakable || info.label && info.label.name === labelNode.name) { + if (info.breakable && info.label && info.label.name === labelNode.name) { + context.report({ + node: labelNode, + message: "This label '{{name}}' is unnecessary.", + data: labelNode, + fix: fixer => fixer.removeRange([sourceCode.getFirstToken(node).range[1], labelNode.range[1]]) + }); + } + return; + } + } + } + + return { + WhileStatement: enterBreakableStatement, + "WhileStatement:exit": exitBreakableStatement, + DoWhileStatement: enterBreakableStatement, + "DoWhileStatement:exit": exitBreakableStatement, + ForStatement: enterBreakableStatement, + "ForStatement:exit": exitBreakableStatement, + ForInStatement: enterBreakableStatement, + "ForInStatement:exit": exitBreakableStatement, + ForOfStatement: enterBreakableStatement, + "ForOfStatement:exit": exitBreakableStatement, + SwitchStatement: enterBreakableStatement, + "SwitchStatement:exit": exitBreakableStatement, + LabeledStatement: enterLabeledStatement, + "LabeledStatement:exit": exitLabeledStatement, + BreakStatement: reportIfUnnecessary, + ContinueStatement: reportIfUnnecessary + }; + } +}; |