Files
react-native-devtools-frontend/node_modules/eslint/lib/rules/no-extra-label.js
T
Tim van der Lippe c8f6ffd7c3 Update ESLint to 6.8.0
Also update the PRESUBMIT linter configuration to make sure
it actually runs the linter when updating ESLint. Otherwise,
it would not properly do the full linter check.

R=jacktfranklin@chromium.org
DISABLE_THIRD_PARTY_CHECK=Update ESLint

Bug: 1068145
Change-Id: Ibf2de156366dc64c90ee1aced5537d2038e7a268
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2137384
Commit-Queue: Tim van der Lippe <tvanderlippe@chromium.org>
Reviewed-by: Jack Franklin <jacktfranklin@chromium.org>
2020-04-06 13:52:18 +00:00

150 lines
5.0 KiB
JavaScript

/**
* @fileoverview Rule to disallow unnecessary labels
* @author Toru Nagashima
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "disallow unnecessary labels",
category: "Best Practices",
recommended: false,
url: "https://eslint.org/docs/rules/no-extra-label"
},
schema: [],
fixable: "code",
messages: {
unexpected: "This label '{{name}}' is unnecessary."
}
},
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,
messageId: "unexpected",
data: labelNode,
fix(fixer) {
const breakOrContinueToken = sourceCode.getFirstToken(node);
if (sourceCode.commentsExistBetween(breakOrContinueToken, labelNode)) {
return null;
}
return fixer.removeRange([breakOrContinueToken.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
};
}
};